前言
lctlct是我一直以来都不想接触的数据结构,就在最近,我终于把这个大坑填上了。
基本定义
边分成两种,轻边和重边。重边构成的链为重链,重链可以只为一个点。
在lctlct中,用一棵splaysplay维护一条重链上的点,对于每一条轻边,必定有一端是连向一条重链上深度最小的点的,我们将这条轻边的信息记录在该重链对应的splaysplay的rootroot,具体的我们用tfaroottfaroot表示在这条重链中深度最小的点在树中的父亲。
splaysplay的中序遍历为11的点为该代表的重链中深度最小的点,中序遍历为22的点为 该代表的重链 中深度次小的点,以此类推。
faxfax为在splaysplay中的xx的父亲,若为该splaysplay 的rootroot,则fax=0fax=0。
splay(x,y)splay(x,y)表示在splaysplay上将xx不停上旋转直到成为的儿子。
基本操作
1、Access(x)Access(x)表示将xx到根路径上的点全部放到一棵内。
2、Makeroot(x)Makeroot(x)表示使x成为它所在的树的根。
3、Cut(x,y)Cut(x,y)删除树边(x,y)(x,y)。
4、Link(x,y)Link(x,y)加入树边(x,y)(x,y)。
操作实现
Access(x)Access(x)
1、splay(x,0)splay(x,0),即将xx旋转至所在树的根,同时断掉在上与右儿子的连边,并使右儿子的tfatfa变为xx。
2、令,执行操作1,把xx的右儿子变为,如此这般直至xx变成该树的根。
//我可能打的比较丑
void Access(int o)
{
splay(o,0);
if(tag[o])down(o);
tfa[rs[o]]=o; fa[rs[o]]=0; rs[o]=0;
while(fa[o]+tfa[o]!=0){
int x=tfa[o];
splay(x,0);
tfa[rs[x]]=x; fa[rs[x]]=0;
rs[x]=o; fa[o]=x; tfa[o]=0;
o=x;
}
}
1、Access(x)Access(x)
2、splay(x,0)splay(x,0)
3、给xx所在的打上翻转标记,表示将重链上的点深度对称互换。
void Makeroot(int o)
{
Access(o);
splay(o,0);
tag[o]=1^tag[o];
}
Cut(x,y)Cut(x,y)
1,Makeroot(x)Makeroot(x)
2,Access(y)Access(y)
3,splay(y,0)splay(y,0)
4,在splaysplay上,把yy的左儿子(即)的连边断掉。
void Cut(int x,int y)
{
makeroot(x); access(y);
splay(y,0);
ls[y]=0; fa[x]=0; tfa[x]=0;
}
Link(x,y)Link(x,y)
1,Makeroot(x)Makeroot(x)
2,令tfax=ytfax=y
void Link(int x,int y)
{
makeroot(x);
tfa[x]=y;
}