LCA问题转化为±1RMQ问题

LCA问题转RMQ问题

DFS整个树,每次进入某个节点都记录下来,就得到了一个2n-1长度的序列D(DFS序)。假设pos[i]表示节点i第一次出现在序列D中的次序,那么欧拉序列就是E[i]=pos[D[i]]。由于从节点u走到节点v的过程中必然经过LCA(u,v)且不会经过LCA(u,v)的父节点,所以节点u、v的LCA就是欧拉序列区间[pos[u], pos[v]]中最小节点(假设为w)所对应的D[w]。

Four Russian

四俄罗斯人算法就是一个分块ST表,将ST表的时间复杂度从O(nlogn)降到了O(nloglogn),只不过常数很大。就是把原数组分为长度为logn的块,将每个块的最值处理成一个ST表,将每个块内部的查询处理成单独的ST表,这样每次查询都可以分解成对不超过3个的ST表查询。

±1RMQ

对于欧拉序列,两个相邻的u和v不是u=v+1就是u=v-1。这里把分块长度改为logn/2,所以可以把每个块转化为logn/2-1长度的二进制序列,对于转化后的二进制序列不同的块称为本质不同的块,而本质相同的块查询结果是相同的。本质不同的块的数量为2^(logn/2)=sqrt(n),暴力处理所有本质不同的块的所有可能查询复杂度为sqrt(n)(logn)^2/4。

单调栈代替暴力求块内RMQ

对一个块内的序列运行单调栈算法,并且每次将每个元素入栈时的栈情况保存下来(因为块长度为logn/2,为节省空间可以使用状压),例如对于的序列1 3 5 2 4,存储的单调栈为00001,00010,00100,01100,10100。

对于块内最大值查询[L,R],只需要找到R时刻单调栈内第一个≥L的元素即可(不证明),写成位操作即为:L+_builtin_ctz(mst[R]>>(L-1))。

比如查询[2,4],首先找到单调栈mst[4]=01100,然后将其右移L-1位使其自然溢出为0110,再用_builtin_ctz计算末尾0的个数为1,最后加上L即为答案3(序号3而非数值3)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值