Link-Cut-Tree 学习笔记

时间:2022-12-28 22:02:42

花了挺长的时间学了LCT,还不是很熟练,还要继续写一些题来熟练。
给初学者的建议:
1、首先先学会链剖和splay,并能掌握它们的原理,熟练写模板。
2、了解LCT和链剖定义的不同,明确Access/Reverse操作各自的作用和原理。
3、在理解操作的原理之后,研究Link/Cut/Find操作如何将它们结合起来。

推荐一个ppt:PoPoQQQ的LCT讲解,挺清楚的,主要是原树和辅助树的关系讲的比较好,但是我不想学指针233

下面稍微摘录一点(From PoPoQQQ)
『LCT能干嘛』
(1)维护一个序列,支持下列操作:
区间求和
区间求最值
区间修改
求连续子段和
这个线段树就可以解决 具体做法不加累述了
(2)维护一个序列,支持下列操作:
区间求和
区间求最值
区间修改
求连续子段和
添加一段区间
删除一段区间
翻转一段区间
对Splay初学者来说几乎是噩梦级别的题目
其实不难(笑
Splay模板题(真心
(3)维护一棵树,支持下列操作:
链上求和
链上求最值
链上修改
子树修改
子树求和
换根
树链剖分!!!
(4)维护一棵树,支持下列操作:
链上求和
链上求最值
链上修改
断开树上的一条边
连接两个点,保证连接后仍然是一棵树
由于树是动态的,我们不能每次操作都重标号一遍 树链剖分搞不了了
然而我们可以沿用树链剖分的轻重链剖分的概念
既然是动态那么我们肯定要把静态的线段树换成动态的Splay
于是就有LCT=树链剖分+Splay

这就是我说为什么学LCT要先学链剖和splay的原因。

『引入一些概念』
Preferred Child:重儿子(为了便于理解这里沿用树链剖分中的命名),重儿子与父亲节点同在一棵Splay中,一个节点最多只能有一个重儿子
Preferred Edge:重(zhòng)边,连接父亲节点和重儿子的边
Preferred Path:重链,由重边及重边连接的节点构成的链

『Auxiliary Tree(辅助树)』
由一条重链上的所有节点所构成的Splay称作这条链的辅助树
每个点的键值为这个点的深度,即这棵Splay的中序遍历是这条链从链顶到链底的所有节点构成的序列
辅助树的根节点的父亲指向链顶的父亲节点,然而链顶的父亲节点的儿子并不指向辅助树的根节点
(儿子人爹&&爹不认儿子)
原树中的重链 -> 辅助树中两个节点位于同一棵Splay中
原树中的轻链 -> 辅助树中子节点所在Splay的根节点的father指向父节点
注意原树与辅助树的结构并不相同
辅助树的根节点≠原树的根节点
辅助树中的father≠原树中的father
附图(依旧From PoPoQQQ)
Link-Cut-Tree 学习笔记
由于要维护的信息已经都在辅助树中维护了,所以LCT无需维护原树,只维护辅助树即可
轻链和重链并不是固定的,随着算法的进行,轻链和重链随算法需要和题目要求而变化,然而无论怎么变化,由这棵辅助树一定能生成原树,并满足辅助树的所有性质

以上内容来自Po姐的ppt,再次深表敬意
那么我来说说LCT的几个操作:
『Access操作』
目的:将x的重边切断,并将x到根的路径上所有的边都搞成重边。
具体实现:根据辅助树按照深度为关键字的性质,重建一颗splay。不断地将一个结点的父亲转到根,然后把这个结点接到它父亲的右儿子。
『Reverse操作』
目的:将原树中的x结点转到根。
具体实现:因为原树是虚树,所以在原树中进行变换实际上是在辅助树中进行变换。首先Access一个点,再将这个点在辅助树中转到根。又是根据辅助书按照深度为关键字的性质,将这个点所在的splay树反转,实际上改变了深度的关系,也就是实现的原树的换根。
『Link操作』
目的:将两个不连通的点连通。换句话来说,合并或扔到一颗树里。
具体实现:首先进行Reverse操作,在原树中将一个点转到那个点所在的树的根。然后将这个转到根的点的father接到另外一个点上。可以进行一次splay来update。
『Cut操作』
目的:将两个连通的点不连通,换句话说,把一棵树拆成两棵树。
具体实现:首先进行Reverse操作,在原树中将一个点转到那个点所在的树的根。然后Access另外一个点,把另外一个点在辅助树中转到根。由于这两个点原先是连通的,那么进行Access操作之后两个点在辅助树中一定是一个位于根,一个位于根的左儿子(深度)。所以在辅助树中把这个边砍掉就行了。
『Find操作』
目的:寻找一个点在原树中的根。
用于:判断两个点的连通性。
具体实现:首先Access这个点,然后在辅助树中将这个点转到根,由于辅助树按照深度为关键字排序,所以不断地向左子树寻找,就可以找到深度最小的根。

差不多就这些把,还有一些奇怪的求和啊,维护最大值最小值什么的和线段树平衡树等数据结构基本一样。也难怪,LCT其实就是线段树、平衡树的延伸。

代码不附了,可以参考本博客LCT的题目(我学的是数组版,实在驾驭不了指针)

那么还需要感谢hzwer和他的模板(虽然有些改动= =)
还要感谢hxy神犇的帮助。