学习笔记::lct

我已经忘了lct

1.lct能干什么

能维护一个序列,能做线段树做的事

能维护一颗静态的树,能做树链剖分和线段树做的事

能维护一个动态的序列,能做splay做的事

能维护一颗动态的树,能做splay和树链剖分的事

所以lct=splay+树链剖分 

2.怎么维护

树链剖分是利用轻重链剖分的性质

那么lct也要维护轻重链,只不过由于有加边和删边所以随时在变化

lct是由若干颗splay组成的,每颗splay代表了一条重链,splay的关键字是深度

在树链剖分里,每次是对一条重链进行操作,然后爬到链顶的父亲进入下一条重链

所以每一颗splay的根节点的父亲就是下一条重链的某个位置

这里splay的父亲和孩子是不对应的,也就是说b是a的父亲,但a不一定是b的孩子

孩子对应的是重链,父亲对应的是轻链

3.操作

所有的link cut都是基于access这一个操作

access(x)操作是指将x到根的链变为重链,并且x为最深的点

怎么实现?因为现在x到根的路径是由很多条重链组成的,现在我们要将这些重链重构变成一条重链

考虑暴力,我们先爬到上一条重链,这个过程是先把x splay到根,那么x的父亲就是上一条重链中的某个位置y,那么我们要把y之后的重链换为x

由于splay维护的是深度,那么x自然是比上一条重链中所有点都要深的,所以我们把ch[y][1]=x,fa[x]=y,相当于强制切换了重链

重复这个过程直到到达根

这个复杂度均摊是log的

然后一系列操作由此衍生

换根:先access(x),将路径提取出来,那么这棵splay里就是x->root构成的重链,然后splay(x),由于x是最深的,那么ch[x][0]=0,所以这个时候我们对换左右儿子就相当于把x的深度变成最浅的了,也就实现了换根

也就是access(x) splay(x) paint(x)

link(x,y):x连到y下面,那么把x当成y的轻儿子,直接rever(x),fa[x]=y

cut(x,y):提取出(x,y)的路径,rever(x),access(y) splay(y),那么x->y的路径就到了一颗splay里,由于x和y相连,并且x现在比y浅,那么x肯定在y的左儿子,直接ch[y][0]=0 fa[x]=0,并且upd(y)

单点加:直接加到对应的点上然后splay一下就行了,lct中编号对应的是原树的编号

区间加:提取出路径,然后就打个标记

原文地址:https://www.cnblogs.com/19992147orz/p/8206693.html