LCT学习笔记
既然大家都说LCT是我在砍树,我也得好好砍不是,所以认真学习了一下Link-Cut-Tree然后来做笔记了。//某lxl看到我就狂D“您是在砍树吗”,真是气人至极
Link-Cut-Tree,顾名思义,最有特色的地方就在Link和Cut。
与链剖相似的是,它也是时常用来维护树链上信息的,但有不同的是,链剖对于每一个非叶子节点一定选一个儿子(重儿子)相连,且一旦连上就不会变,而LCT的每个非叶子节点所选来连的儿子数<=1,还总是变.如果要打个详细的比方的话,那链剖就是木心的从前慢里面的那把锁,锁上之后别人就懂了,而LCT就像当今的新时代青年,可以不结婚,也可以结婚,也可以结了婚离婚再结婚。总之,变脸比翻书还快,但正是因为这样,才自由可变化,适用范围更广。
LCT,因为动态是动态树,所以也要用动态的数据结构来维护,这里选用Splay。
Question1:
Splay维护什么?
以深度为键值,维护链上信息(但我们其实并不需要真正的在节点信息里面记上深度),splay可支持的所有信息操作。
Question2:
这么多棵splay那一定有很多根吧,那岂不是根满天飞!
不不不你太天真了,我们只是换了一种判断根的方式,每一棵splay的根的father是原树上这条链深度最浅的那个点的father。
下面介绍LCT一些基本操作:
0.isroot(u)判断u是否是splay上的根节点
1.access(u)表示将u到根节点这条链变成实链,并将u到u的儿子断掉。
2.makeroot(u)将u变为新的根
access(u)+reverse(u)//reverse是splay里的操作
为什么这样?因为原来是按照深度为键值建的splay,我如今要换根,那么u的深度一定要变为最小,u的father次小这样依次类推。巧妙地发现只用翻转一下splay区间就好啦~
3.link(u,v)将本不联通的u,v连上一条边
makeroot(u)
u->pre=v;//这里连的是虚边,所以并不管v的儿子是不是u
access(v)//其实我并不知道这里为什么大家都会习惯性的写个access,以后其实会access并更新信息的
4.cut(u,v)将本在树上有连边的u和v之间的这一条边断掉
makeroot(u)
access(v)//v不是根则v的深度一定比u大,在u的右子树上,而因为直接连边,所以是他的右儿子
splay(v)//此时u变成了v的左儿子
v->ch[0]=nil;
u->pre=nil;'//删掉
基本的操作就这些,本来我也是不怎么会写的,看了zcy朱神的代码之后觉得神清气爽好看极了就跟着他的板一起写了。
下面贴板
//小小感怀一下,noip之前我还是个连splay都不敢写的naive少年LCT更是不敢想,果然人是需要迈步的勇气的阿!
//本来朱神的板我的zzk他是写的hja,我一想不敢亵渎仰慕的大神就只好换啦