[P3690]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。

模板,不解释,详见代码

#include<bits/stdc++.h>
using namespace std;
const int mxn=3e5+5;
int n,m,t[mxn],fa[mxn],st[mxn],rev[mxn],val[mxn],ch[mxn][2];

namespace lct {
    int isnotrt(int x) {
        return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
    };
    void push_up(int x) {
        t[x]=t[ch[x][0]]^t[ch[x][1]]^val[x];
    };
    void push_down(int x) {
        if(rev[x]) {
            rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
            swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
            swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
            rev[x]=0;
        }
    }
    void rotate(int x) {
        int y=fa[x],z=fa[y],tp=ch[y][1]==x;
        if(isnotrt(y)) ch[z][ch[z][1]==y]=x;/**/ fa[x]=z;
        ch[y][tp]=ch[x][tp^1],fa[ch[x][tp^1]]=y;
        ch[x][tp^1]=y,fa[y]=x;
        push_up(y),push_up(x);
    };
    void splay(int x) {
        int tp=x,s=0; st[++s]=tp;
        while(isnotrt(tp)) st[++s]=tp=fa[tp];
        while(s) push_down(st[s--]);
        while(isnotrt(x)) {
            int y=fa[x],z=fa[y];
            if(isnotrt(y))  
                (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
            rotate(x);  
        }
    };
    void access(int x) {
        for(int y=0;x;x=fa[y=x])
            splay(x),ch[x][1]=y,push_up(x);
    };
    void makert(int x) {
        access(x); splay(x); 
        swap(ch[x][0],ch[x][1]);
        rev[x]^=1;
    };
    int findrt(int x) {
        access(x); splay(x);
        while(ch[x][0]) push_down(x),x=ch[x][0];
        splay(x); return x;
    };
    void split(int x,int y) {
        makert(x); access(y); splay(y);
    };
    void link(int x,int y) {
        makert(x); 
        if(findrt(y)!=x) fa[x]=y;
    };
    void cut(int x,int y) {
        makert(x);
        if(findrt(y)==x/**/&&fa[y]==x&&!ch[y][0]) {
            fa[y]=ch[x][1]=0;
            push_up(x);
        }
    };
}
using namespace lct;

int main()
{
    scanf("%d%d",&n,&m); int opt,x,y;
    for(int i=1;i<=n;++i) scanf("%d",val+i);
    while(m--) {
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==0) split(x,y),printf("%d\n",t[y]);
        else if(opt==1) link(x,y);
        else if(opt==2) cut(x,y);
        else splay(x),val[x]=y;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/list1/p/10375845.html
0条评论
添加一条新回复