P3690 【模板】动态树(Link Cut Tree)疑惑与解答
https://www.cnblogs.com/flashhu/p/8324551.html
https://www.cnblogs.com/cjyyb/p/7499020.html
1
splay 是二叉树,要满足权值性质。在 LCT 中满足的性质是权值为深度,即一棵 splay 维护的联通块满足中序遍历后的序列在原树中是一条链。(深度递增),splay 的树根的 fa 指向的是原树中这条链实实在在的父亲,所以我们在一系列操作中都要维护这个性质,才能实现原树中自下而上跳链。
2
rotate,因为 \(x\) 是 \(y\) 的 ident(x) 子,所以 \(y\) 是 \(x\) 的 ident(x)^1 子,然后本来 \(x\) 的这个儿子被 \(y\) 占了,又因为这个儿子在 \(y\) 的 ident(x) 子树,所以这个儿子是 \(y\) 的 ident(x) 子。
3
\(splay\) 看父亲和父亲的父亲都是为了降低复杂度。总之就是,旋 \(1\) 次就到根了。否则的话,看是否 \(3\) 点共线,是的话就先旋父亲,不是就对 \(x\) 旋 \(2\) 次。效果上都是对链的叉化。
4
为什么
// 回顾一下代码
inline int Access(int x) {
int p;
for (p = 0; x; p = x, x = f[x]) {
Splay(x), ch[x][1] = p, PushUp(x);
}
return p;
}
考虑需要在 access 过程中满足一系列性质。
-
access 操作只是在原树中拉一条从根到 x 的实链,也就是说 \(x\) 不该有右儿子。
-
当我们每次 splay(x) 时,此时的 fa[x] 对应原树 x 所在 splay 集合构成的一条链 的父亲,也就是说 \(x,p\) 现在都是它们对应 splay 的树根,且有 \(fa[p]=x\),那么是不是可以在原树上看成上下接壤的 2 条链,自然深度关系就出来了。
-
为什么左儿子都可以不管呢?因为每次合并 2 个 splay 时相当于合并 2 条深度递增的链(有 \(fa[p]=x\) 保证,也就是 p 这个 splay 构成的链一定在 x 这个 splay 构成的链之下。性质)。那么只需要考虑右儿子即可。
-
原先 \(x\) 的右儿子现在自然成为了它所在 splay 的根了。那么是否满足它的父亲(即 x),与它在原树上也是父子关系呢?考虑原先没有实变虚,那么显然在原树上是这样一条链 \(ls[x]\to x \to rs[x]\),\(ls,rs\) 指左右儿子中序遍历后构成的,那么显然在 \(rs[x]\) 中存在一个点 \(q\),满足在原树上 \(dep[q]=dep[x]+1\),不然不可能原先在同一个 splay。于是这样就好办了,实变虚后,\(rs[x]\) 单独对应树上一条链,且里面存在一个点的深度为树根父亲深度 \(+1\),自然满足 splay 的树根的 fa 指向的是原树中这条链实实在在的父亲 这个性质了。
连续两次 Access 操作时,第二次 Access 操作的返回值等于这两个节点的 LCA.
因为这个 p 是最后一个穿过虚边的位置。
然后第一次 access 之后会把 x 到根打成实链,第二次 access y 会在 lca(x,y) 的时候经过最后一条虚边。
p 都知道吧?模拟一下就可以知道。那么 lca(x,y) 是不是一定在实链中?那么从 y 一直 splay 上去,是不是最后 2 个 splay 合并完就是在 lca(x,y) 初,因为 access(x) 把 x 与根放在一个 splay,再从这个 splay 跳上去就跳出去了。所以在最后合并的位置就是 lca(x,y)。
5
int fd_root(int x) {
access(x); splay(x);
push_down(x);
while(ls) x=ls,push_down(x);
splay(x);
return x;
}
bool cut(int x,int y) {
make_root(x);
if(fd_root(y)!=x||ch[0][y]||fa[y]!=x) return 0;
fa[y]=ch[1][x]=0;
return 1;
}
cut 的时候判什么?显然 make_root 后 x,y 在同一个 splay,因为 make_root 后 x 就是原树的根,find_root 时已经将 y 与 x 打通实链,那么看看根是不是 x,又因为 y 一定是 x 的右儿子(在原树上上下关系),且因为上下关系,y 不能有左儿子 z,不然就出现 depx<depz<depy 的局面了,也就是说在原树上 x,y 是长度大于 2 的链的 2 个端点罢了。