LCT是用来维护有根树森林的,要支持以下操作。
make-tree(v):让节点v单独变成一个有根树。
link(v, w):把v挂在w上。
cut(v, w):让v不再是w的子节点。
find-root(v):找到v所在的树的根。
find-root(v)的时候,如果直接用原来的有根树,那就要一个一个往上跳,直到跳到根节点。我们考虑采用树链剖分的方式,将这棵有根树剖成一条一条竖着的链,如果每条链都可以快速求出其最上面的节点的话,那就可以沿着这些链快速跳到根。
如果采用轻重链剖分的方式,那么树就必须是静态的,而且复杂度是
LCT是一种对有根树进行动态剖分的方法,可以达到全局平衡的效果,从而实现
可以看到,这些链经常要进行拆分重组,所以使用splay来维护这些链,在原树中越高层的节点在splay里越小(其实反过来应该也可以)。这样,cut和link也成为了可能。cut(v, parent(v))时,同样先access(v),这时v在splay里是最大的,而且是根,所以直接把v从splay里断开即可。link(v, w)时,先access(v)和access(w),由于v是要挂上去的子树的根,所以其在所在的splay里是最小的节点,access(v)之后就变成了splay的根,而且没有左子树。access(w)之后,w同样成为了它到根的链上的splay的根,然后就可以直接把w挂到v的splay的左子树上。
看起来好像是
实际上,根据这篇文章:SPOJ375 QTREE
解法的一些研究,如果我们在轻重链剖分中,把维护重链的线段树换成splay,那由于splay会自适应地减少经常被访问的节点的高度,所以也能实现全局平衡的效果,复杂度同样为不过我没看懂。
如何实现可以看这里:LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
一些能用LCT做的题:LCT总结——应用篇(附题单)(LCT)
维护原树子树上的信息可以用LCT的升级版——top tree:
noip退役选手的another扯淡Top
tree 相关东西的理论、用法和实现
参考文献: