[模板]Link Cut Tree

传送门

Description

给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。

0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。

1:后接两个整数(x,y),代表连接x到y,若x到y已经联通则无需连接。

2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。

3:后接两个整数(x,y),代表将点x上的权值变成y。

Solution

\(Link\ Cut\ Tree\)模板题

\(findroot\)后要\(Splay\)到根?不然复杂度不保证???

在洛谷上实测\(535ms\),还算比较快吧

函数变量名奇异+神仙缩行\(\rightarrow\) 还是别看了


Code 

//2019.1.26 18:41-22:54
#include<bits/stdc++.h>
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}
class Link_Cut_Tree
{
    #define MN 300005 
    private:
        int N,fa[MN],c[MN][2],st[MN],val[MN],X[MN];
        bool rev[MN];
        inline bool nrt(int x){return c[fa[x]][0]==x||c[fa[x]][1]==x;}
        inline void Rev(int x){rev[x]^=1;std::swap(c[x][0],c[x][1]);}
        inline void up(int x){X[x]=X[c[x][0]]^X[c[x][1]]^val[x];}
        inline void down(int x){if(x&&rev[x])Rev(c[x][0]),Rev(c[x][1]),rev[x]=0;}
        #define get(x) (c[fa[x]][1]==x)
        inline void rotate(int x)
        {
            int y=fa[x],z=fa[y],l=get(x),r=l^1;if(nrt(y))c[z][get(y)]=x;fa[x]=z;
            c[y][l]=c[x][r];fa[c[x][r]]=y;c[x][r]=y;fa[y]=x;up(y);
        }
        inline void Splay(int x)
        {
            static int top,q[MN];q[top=1]=x;register int i;
            for(i=x;nrt(i);i=fa[i]) q[++top]=fa[i];for(;top;--top) down(q[top]);
            for(;nrt(x);rotate(x))if(nrt(fa[x])) rotate(get(fa[x])^get(x)?x:fa[x]);up(x);
        }
        #undef get
        inline void access(int x){register int i;for(i=0;x;x=fa[i=x])Splay(x),c[x][1]=i,up(x);}
        inline void mkrt(int x){access(x);Splay(x);Rev(x);}
        inline int fdrt(int x){access(x),Splay(x);for(;c[x][0];down(c[x][0]),x=c[x][0]);Splay(x);return x;}
        inline void Split(int x,int y){mkrt(x);access(y);Splay(y);}
    public:
        inline void init(int n){register int i;for(i=1;i<=n;++i) val[i]=X[i]=read();}
        void Link(int x,int y){mkrt(x);if(fdrt(y)!=x)fa[x]=y;}
        void Cut(int x,int y){Split(x,y);if(c[y][0]==x&&!c[x][1])c[y][0]=fa[x]=0,up(y);}
        inline int Query(int x,int y){if(x==y) return val[x];Split(x,y);return X[y];}
        inline void Modify(int x,int V){Splay(x);val[x]=V;up(x);}
    #undef MN
}T;
int main()
{
    register int n=read(),m=read(),opt,x;T.init(n);
    while(m--)
    {
        opt=read(),x=read();
        switch(opt)
        {
            case 0:printf("%d\n",T.Query(x,read()));break;
            case 1:T.Link(x,read());break;
            case 2:T.Cut(x,read());break;
            case 3:T.Modify(x,read());break;
        }
    }
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

猜你喜欢

转载自www.cnblogs.com/PaperCloud/p/10325245.html