您的位置:首页 > 其它

Link-Cut-Tree 学习笔记

2016-03-27 15:02 281 查看
花了挺长的时间学了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)



由于要维护的信息已经都在辅助树中维护了,所以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神犇的帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: