Link Cut Tree(动态树)

来源:互联网 发布:网络书香讲坛 编辑:程序博客网 时间:2024/05/16 03:12

模板题
感觉其实LCT就是在用splay维护树剖。。。
贴两个blog

Candy:
https://www.cnblogs.com/candy99/p/6271344.html
zyf2000:
http://blog.csdn.net/clove_unique/article/details/50991804

这两个看完应该就懂了,代码的话,可以抄Candy的
(除了那个诡异的namespace,其他都不错)
我把Candy的代码简单改了改,没啥大变化
看自己的个人习惯,看着哪个顺眼就抄哪个吧
我的代码:

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<cstdlib>#define ll long longusing namespace std;inline int read(){    int x=0;char ch=' ';int f=1;    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();    if(ch=='-')f=-1,ch=getchar();    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();    return x*f;}namespace LCT{    #define lc ch[x][0]    #define rc ch[x][1]    const int N=3e5+5;    int ch[N][2],f[N],rev[N],sum[N],val[N];    inline bool get(int x){return ch[f[x]][1]==x;}    inline bool isroot(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;}    inline void update(int x){sum[x]=sum[lc]^sum[rc]^val[x];}    inline void rever(int x){rev[x]^=1;swap(lc,rc);}    inline void pushdown(int x){        if(rev[x]){            if(lc)rever(lc);            if(rc)rever(rc);            rev[x]=0;        }    }    inline void pd(int x){if(!isroot(x))pd(f[x]);pushdown(x);}    inline void rotate(int x){        int y=f[x],z=f[y],w=get(x);        f[x]=z;if(!isroot(y))ch[z][get(y)]=x;        ch[y][w]=ch[x][w^1];f[ch[y][w]]=y;        ch[x][w^1]=y;f[y]=x;        update(y);update(x);    }    inline void splay(int x){        pd(x);        for(int fa=f[x];!isroot(x);rotate(x),fa=f[x])            if(!isroot(fa))                rotate((get(x)==get(fa))?fa:x);    }    inline void access(int x){        for(int y=0;x;y=x,x=f[x])splay(x),rc=y,update(x);    }    inline void make(int x){        access(x);splay(x);rever(x);    }    inline int find(int x){        access(x);splay(x);        while(lc)x=lc;        return x;    }    inline void split(int x,int y){        make(x);access(y);splay(y);    }    inline void link(int x,int y){        make(x);f[x]=y;    }    inline void cut(int x,int y){        split(x,y);        f[x]=ch[y][0]=0;update(y);    }}using namespace LCT;int n,m;int main(){    n=read();m=read();    for(int i=1;i<=n;i++)val[i]=read();    while(m--){        int opt=read(),x=read(),y=read();        if(opt==0){split(x,y);printf("%d\n",sum[y]);}        if(opt==1){if(find(x)!=find(y))link(x,y);}        if(opt==2){if(find(x)==find(y))cut(x,y);}        if(opt==3){access(x);splay(x);val[x]=y;update(x);}    }    return 0;}