update
博主就是个超级大傻逼,其实四毛子算法中,可以状压优先队列中的元素,于是就解决了rmq,比下面的套娃做法看起来还更好写 。
众所周知,rmq和lca有着诸多关系
今天就听我扯淡一番
欢淫来到不说人话系列(
其实很早就有人写过相关东西了(
我奶奶都会的做法
O ( n 2 ) O(n^2) O(n2) ,空间 O ( n ) O(n) O(n)
大家普遍会的做法
(1)倍增求lca:
O
(
n
l
o
g
n
)
−
O
(
l
o
g
n
)
O(nlogn)-O(logn)
O(nlogn)−O(logn),在线
(2)树链剖分求lca:
O
(
n
)
−
O
(
l
o
g
n
)
O(n)-O(logn)
O(n)−O(logn),在线,常数极小
(3)ST表求解rmq
O
(
n
l
o
g
n
)
−
O
(
1
)
O(nlogn)-O(1)
O(nlogn)−O(1),在线
(4)lca转成欧拉序中深度最小的问题,然后ST表
O
(
n
l
o
g
n
)
−
O
(
1
)
O(nlogn)-O(1)
O(nlogn)−O(1),在线
(5)rmq转成笛卡尔树然后求lca,禁止套娃(4),可以
O
(
n
−
n
l
o
g
n
)
−
O
(
l
o
g
n
)
O(n-nlogn)-O(logn)
O(n−nlogn)−O(logn),在线
BJOI2020rk4,5修罗场对决要求会的算法
这里的做法是离线的
设你的并查集常数是
k
k
k
LCA离线tarjan:
O
(
n
)
−
O
(
k
)
O(n)-O(k)
O(n)−O(k)
rmq转成笛卡尔树然后就
O
(
n
)
−
O
(
k
)
O(n)-O(k)
O(n)−O(k)
实际上类似单调栈那样,离线后固定右端点进行询问
O
(
n
)
−
O
(
k
)
O(n)-O(k)
O(n)−O(k)
topcoder的做法
给lca和rmq提出了个
O
(
n
)
−
O
(
1
)
O(n)-O(1)
O(n)−O(1)的在线做法
注意连并查集的常数都没有
首先我们得知rmq可以通过笛卡尔树lca解决,lca可以通过欧拉序的rmq解决,然后我们又可以把欧拉序的rmq问题变成笛卡尔树上的lca问题
禁止套娃
所以问题就变成了解决欧拉序的rmq,你这不转转转转回原点吗这是营销号文章大家快点走
总之我们需要解决欧拉序的rmq问题
注意到欧拉序有个很好的性质,相邻两个节点深度相差为1
我们分块,每块大小为
S
=
⌊
l
o
g
2
n
2
⌋
S=\lfloor \frac{log_2n}{2}\rfloor
S=⌊2log2n⌋
没块处理出最小值,对这些最小值做个ST表
复杂度为
O
(
n
S
∗
l
o
g
2
n
S
)
=
O
(
n
)
O(\frac{n}{S}*log_2\frac{n}{S})=O(n)
O(Sn∗log2Sn)=O(n)
散块部分维护块内前缀和后缀最小值
这样解决了跨快的问题
现在我们解决快内的问题
注意到如果块内对深度做差分,得到差分序列可能有
O
(
2
S
i
z
)
=
O
(
n
)
O(2^{Siz})=O(\sqrt n)
O(2Siz)=O(n)
这些序列本质相同,分别处理
然后时空复杂度就是
O
(
n
l
o
g
2
n
2
)
O(\sqrt n log_2n^2)
O(nlog2n2)纯路人n是10^10吗QAQ
所以时空复杂度是
O
(
n
+
n
l
o
g
2
n
2
)
O(n+\sqrt n log_2n^2)
O(n+nlog2n2)
没有代码可以走了
一般来说,树剖,倍增,ST表够你用了
只要你没有不幸碰到修罗场这样的事情
不过不会也没多大关系因为oyyp不会该修罗技巧最后还是进队了orz