lct学习笔记

来源:互联网 发布:网络解锁助手1.0.9 编辑:程序博客网 时间:2024/05/16 00:57

lct不能够实现“对某个点的子树进行的某些操作”(但可以实现类似求子树大小的简单操作),然而对于大部分动态树问题来说还是够用了。
主要的四个操作。
1,Access(x),把原树上x到根路径上的所有点放到同一颗splay里面
2,Makeroot(x),让x成为所在树的根
3,Cut(x,y),切断相邻的节点x,y的边
4,Link(x,y),让x,y连一条树边,成为属于原图的同一棵树。

基本定义
splay(x,y)表示x旋转到为y的儿子
fa[x]为splay中的x的父亲。
其中每个splay的根root都记录了一个tfa[root]表示在这棵splay中深度最小的点在树中的父亲。

Access(x)
1,splay(x,0),splay上,断开右子树,右子树的顶端y记录tfa[y]=x
2,令last=x,x=tfa[x],执行操作1,并让last所在子树成为x的右子树。(splay上)
3,重复操作2直至tfa[x]=0。

Makeroot(x)
1,Acccess(x)
2,splay(x,0)
3,给x所在的splay打翻转标记
access(x)之后,原树其他点到这个重链上的所有点都是轻边了,无论是这个重链的谁作为根,轻边的信息都不会变质。而x为重链的最深点,把它作为根,那么深度顺序就反了过来,所以翻转。

Cut(x,y)
1,Makeroot(x)
2,Access(y)
3,splay(y,0)
4,在splay上,把y的左子树断掉。
makeroot(x)后x肯定是y的父亲了。为了其他点的信息不被破坏,我们断掉y所在的重链,让x,y于同一重链,把y的左子树断掉,即x和y断掉了,此时tfa[y]肯定是0,因为x是根。

Link(x,y)
1,Makeroot(x)
2,splay(x,0)
3,tfa[x]=y
makeroot(x)后再把x旋到根,tfa[x]=0,直接连向y即可。

模板

bool pd(int x){return(tree[fa[x]][0]==x)?0:1;}void re(int x){    if (!x) return;    bz[x]^=1,swap(tree[x][0],tree[x][1]);}void update(int x){    int l=tree[x][0],r=tree[x][1];    num[x]=max(max(num[l],num[r]),x);}void clear(int x){    int l=tree[x][0],r=tree[x][1];    if (bz[x]) re(l),re(r);    bz[x]=0;}void rotate(int x){    int y=fa[x],z=pd(x),z1=pd(y);    if (tree[y][z]=tree[x][z^1]) fa[tree[y][z]]=y;    if (fa[x]=fa[y]) tree[fa[x]][z1]=x;    if (tfa[y]) tfa[x]=tfa[y],tfa[y]=0;    fa[y]=x,tree[x][z^1]=y,update(y);}void chu(int x,int y){    q[0]=0;    for(;x!=y;x=fa[x]) q[++q[0]]=x;    for(;q[0];q[0]--) clear(q[q[0]]);}void splay(int x,int y){    chu(x,y);    while (fa[x]!=y){        int f=fa[x];        if (fa[f]!=y){            if (pd(x)==pd(f)) rotate(f);else rotate(x);        }rotate(x);    }update(x);}void access(int x){    int last=0,y;    for(;x;last=x,x=tfa[x]){        splay(x,0);        y=tree[x][1];        if (y) tree[x][1]=0,fa[y]=0,tfa[y]=x;        if (last)tree[x][1]=last,fa[last]=x,tfa[last]=0;        update(x);    }}void makeroot(int x){    access(x);    splay(x,0);    re(x);}void link(int x,int y){    makeroot(x);    splay(x,0);    tfa[x]=y;}void cut(int x,int y){    makeroot(x);    access(y);    splay(y,0);    tree[y][0]=0,fa[x]=0,update(y);}
0 0