2018年3月7日训练日记

RMQ问题中的ST算法:(摘自某位大佬)

ST(Sparse Table)算法
定义:f[i][j]表示i到i+2^j-1这段区间的最大值。
预处理:f[i][0]=a[i]。即i到i区间的最大值就是a[i]。
状态转移:将f[i][j]平均分成两段,一段为f[i][j-1],另一段为f[i+2^(j-1)][j-1]。
两段的长度均为2^j-1。f[i][j]的最大值即这两段的最大值中的最大值。

得到f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1])。

void RMQ(int N){
    /*注意外部循环从j开始,
    因为初始状态为f[i][0],
    以i为外层会有一些状态遍历不到。*/ 
    for(int j=1;j<=20;j++)  
        for(int i=1;i<=N;i++)
            if(i+(1<<j)-1<=N)
                f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
 查询:需要查询的区间为[i,j],则需要找到两个覆盖这个闭区间的最小幂区间。这两个区间可以重复,因为两个区间是否相交对区间最值没有影响。(如下图)


i+2^k-1>=j-2^k+1 自己画了下,还是很容易验证的。所以一定能包含i到j整个区间。

当然求区间和就肯定不行了。这也就是RMQ的限制性。
因为区间的长度为j-i+1,所以可以取k=log2(j-i+1)。

RMQ(A,i,j)=max(f[i][k],f[j-2^k+1][k])

若在一棵树上进行路径的权值修改,询问路径权值和、路径权值极值树上倍增树链剖分都能解决后两种问题,而且树上倍增要比树链剖分代码好打,但是树链剖分能处理权值修改问题(第一种问题),而树上倍增不能。树剖的用处比树上倍增多得多,树上倍增能做的题树剖一定能做,反过来就不行了。

树剖我记得之前看过一点,但是去翻了自己的博客居然没找到,只有自己当时打的模板。。。以下树剖内容来自(路人黑的纸巾

轻儿子和重儿子
设xsize表示以x为根的子树的节点个数 
对于每个非叶子节点y,y的儿子所有中size最大的儿子就是重儿子(两个或以上都最大的话,任意选一个) 
而y其它的儿子,都是轻儿子 (轻儿子通常没有用,我们可以不去考虑它)
重边、轻边和重链
重儿子与其父亲之间的路径,就是重边 
不是重边的边均为轻边 
多条重边相连为一条重链

相关性质:

  • 若x是轻儿子,则有xsize<=father(x)size2

  • 从根到某一点的路径上,不超过log2n重链,不超过log2n轻链

预处理

首先用一个 dfs遍历,求出每个点的 depthfather size 以及重儿子heavy_son

其次再用一个dfs剖分,第二个dfs维护什么呢?

  • 优先走重边的原则,遍历出来一个dfs序
  • xtop表示x位于的重链上的顶端节点编号
  • to_tree[x]表示x在线段树中的位置
  • 对于线段树中的第y个位置,to_num[y]为它对应的dfs序中的位置

剖分完以后,每一条重链相当于一个区间,我们维护处理完的数据结构即可

我们把上面那棵树剖分完以后线段树中的点顺序是这样的: 
1,3,6,10,8,9,7,2,5,4 (加粗的点是在重链上的点) 
在同一条重链上的点,在线段树的顺序中要连在一起(否则怎么维护呢)

剖树的时间复杂度 O(n)O(n)

维护以及在线操作

因为已经搞过to_tree了,通过to_tree的标号在线段树中用单点修改即可 
时间复杂度是线段树修改的O(log2n)O(log2n)

询问xxyy路径的极值(或者路径和等等),和求LCALCA一样边向上跳边记录答案 
这里记录的答案通过查询数据结构得到 

用最普通的数据结构线段树来维护树链剖分的时间复杂度是O(n+qlog2n)


hiho600题 go!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值