码迷,mamicode.com
首页 > 其他好文 > 详细

寒武纪camp网络测试赛

时间:2018-01-16 12:24:42      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:时间复杂度   一个   ble   strong   problem   ext   nlog   答案   class   

寒武纪camp网络测试赛

地址:oj点我进入

A(树形dp+树链剖分)

题意:

技术分享图片

分析:

  考虑树形dp,f0(x)和f1(x)分别表示以x为根的子树,不取x点或取x点的最大合法子集的元素个数

  那么对于一个询问来说,答案就是max(f0(x),f1(x)),我们的任务就是对于每次修改操作维护所有f数组的变化

  假设我们新加入了一个x节点,很明显只有x以及x的祖先们的f值会改变

  首先f1(x)=f0(x)+1,因为我多取一个x节点一定是合法的(题目保证权值从小到大)

  然后考虑x的祖先fa,应该有f0(fa)=f0(fa)+1,因为fa的子树里面可以多选一个点x

  但问题是x的某个祖先fa可能f0值不会变,因为它的最优决策可能是某个f1(y),其中dep(fa)<dep(y)<dep(x) 且三个在一条链上,所以y及y以上部分的f值都不会改变

  那么什么时候会出现这种情况呢,其实就是f1(y)>=f0(y)+1这时候,因为这时候我选择“放y这个点”不比“不放y这个点且放刚进入的x点”

  于是我们想到了很自然的维护方法,对于每次新来的点x,一直向上跳,跳到第一个f1(y)>=f0(y)+1的位置停止,将father(x)~y这一段的点的f0全部加上1

  那当然这样会TLE,我们只能用数据结构来维护这样的事

  在树上给一条链加上1这件事很自然可以想到用树链剖分+线段树去做,问题是如何找到最近的那个f1(y)>=f0(y)+1的点

  我们发现这样的y只可能是目前的所有C操作里面的所有点,即目前有赋权值的点,而不是其它的未赋权值的点,换句话说我们的给一段点的f0全部加上1这样的操作不会在加的过程中产生新的y,也就是说加1操作和维护这样的y是独立的

  于是我们可以把所有的f1(y)>=f0(y)+1打个标记,对于每个新加入的x,我们在树上找到离x最近的带标记的祖先y,然后将这一段+1,同时将y的标记消除(因为y已经变成了f1(y)=f0(y)了)

  那么怎么找最近的带标记的祖先y呢,我们可以顺着重链向上跳,然后每次在线段树上找最靠右边的标记节点,这样是O(logn * logn)的

  所以总的时间复杂度就是$O(nlog^2n)$的

 

寒武纪camp网络测试赛

标签:时间复杂度   一个   ble   strong   problem   ext   nlog   答案   class   

原文地址:https://www.cnblogs.com/wmrv587/p/8295688.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!