Link-Cut-Tree学习笔记
P3690 【模板】动态树(Link Cut Tree)
基本概念其他博客里都有,就不重复了。
- 本质维护一个文艺splay森林。
- 每一个splay中的点集合在实树中构成一条链
- 其中splay保证以每个节点在实树中的
dpt 为key ,是一棵bst。 - 一棵splay的根也会有一个
fa ,但那个fa 却不认它这个son - 虚边,即根与外界连的那条边,在实树上存在于该splay最左边(即
key 最小,dpt 最浅)的那个点与上一条中的fa 之间。 - 实边,即一棵splay内部的边,与实树的边其实并没有关系。
- 个人认为过于强调这两种边与 轻重链剖分 中的轻边与重边的关系并不恰当
*实树:题目里给出的,真实存在的那一棵树。
有关文艺splay部分,参见P3391 【模板】文艺平衡树,即带翻转的splay
access(x):最基础的操作,使
从
while(x)中逐步解析:
splay(x);
显然, 将
heavy_link(son,x,1);
若是第一次循环,转换
在
pushup(x);
都连边了肯定要pushup(x)的嘛
-
son=x; -
x=tr[x].fa;
往上爬
inline void access(int x){
int son=0;
while(x){
splay(x);
heavy_link(son,x,1);
pushup(x);
son=x;
x=tr[x].fa;
}
}
以上,循环中每次一个一个heavy_link,把access(x)的目的了。
makeroot(x)使
想象我们的实树,如何让
(自己脑补动图)
考虑改变splay中每个节点的
因此在搞清楚之前我们先来access(x)吧!
access(x);
就是他那个功能
容易发现,现在需要改变的splay内相对
那么考虑那条链上节点的
(再自己脑补标上
没错,只需要对整个splay,即整条链,做一个reverse(x)就可以了
reverse(x);
原理与作用参见P3391 【模板】文艺平衡树。
pushup(x);
日常pushup(x)
inline void makeroot(const int &x){
access(x);
reverse(x);
pushup(x);
}
以上,makeroot(x)。
findroot(x),找到
split(x,y),使
link(x,y),在
cut(x,y),切断
modify(x,val),修改
有关链上询问,只需split(x,y),然后