P3690 【模板】动态树(Link Cut Tree)疑惑与解答

https://oiwiki.org/ds/lct/

https://www.codein.icu/lct/

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 过程中满足一系列性质。

  1. access 操作只是在原树中拉一条从根到 x 的实链,也就是说 \(x\) 不该有右儿子

  2. 当我们每次 splay(x) 时,此时的 fa[x] 对应原树 x 所在 splay 集合构成的一条链 的父亲,也就是说 \(x,p\) 现在都是它们对应 splay 的树根,且有 \(fa[p]=x\),那么是不是可以在原树上看成上下接壤的 2 条链,自然深度关系就出来了。

  3. 为什么左儿子都可以不管呢?因为每次合并 2 个 splay 时相当于合并 2 条深度递增的链(有 \(fa[p]=x\) 保证,也就是 p 这个 splay 构成的链一定在 x 这个 splay 构成的链之下。性质)。那么只需要考虑右儿子即可。

  4. 原先 \(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 个端点罢了。

posted @ 2022-07-21 20:50  FxorG  阅读(44)  评论(0编辑  收藏  举报