3282: 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。
Input
第1行两个整数,分别为N和M,代表点数和操作数。
第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。
Output
对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。
Sample Input
3 3
1
2
3
1 1 2
0 1 2
0 1 1
1
2
3
1 1 2
0 1 2
0 1 1
Sample Output
3
1
1
HINT
1<=N,M<=300000
总算是理解了LCT。。。splay可以维护一切可合并的操作,所以异或也可以维护。。。
然后再在splay上维护值即可。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 500000+5 14 #define maxm 10000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 int n,m,v[maxn],sum[maxn],c[maxn][2],fa[maxn],sta[maxn],top; 30 bool rev[maxn]; 31 bool isroot(int x){ 32 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 33 } 34 void pushup(int x){ 35 sum[x]=v[x]^sum[c[x][0]]^sum[c[x][1]]; 36 } 37 void rever(int x){ 38 rev[x]^=1; 39 swap(c[x][0],c[x][1]); 40 } 41 void pushdown(int x){ 42 if(!rev[x])return ; 43 rever(c[x][0]);rever(c[x][1]); 44 rev[x]=0; 45 } 46 void rotate(int x){ 47 int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; 48 if(!isroot(y))c[z][c[z][1]==y]=x; 49 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 50 c[y][l]=c[x][r];c[x][r]=y; 51 pushup(y);pushup(x); 52 } 53 void splay(int x){ 54 int top=0;sta[++top]=x; 55 for(int y=x;!isroot(y);y=fa[y])sta[++top]=fa[y]; 56 for(;top;)pushdown(sta[top--]); 57 while(!isroot(x)){ 58 int y=fa[x],z=fa[y]; 59 if(!isroot(y)){ 60 if(c[z][0]==y^c[y][0]==x) 61 rotate(x); 62 else rotate(y); 63 } 64 rotate(x); 65 } 66 } 67 void access(int x){ 68 for(int y=0;x;x=fa[x]){ 69 splay(x);c[x][1]=y;pushup(x);y=x; 70 } 71 } 72 void makeroot(int x){ 73 access(x);splay(x);rever(x); 74 } 75 void split(int x,int y){ 76 makeroot(x);access(y);splay(y); 77 } 78 int findroot(int x){ 79 access(x); 80 while(!isroot(x))x=fa[x]; 81 return x; 82 } 83 void link(int x,int y){ 84 if(findroot(x)==findroot(y))return ; 85 makeroot(x);fa[x]=y;splay(x); 86 } 87 void cut(int x,int y){ 88 split(x,y);if(c[y][0]==x)c[y][0]=fa[x]=0; 89 } 90 int main(){ 91 //freopen("input.txt","r",stdin); 92 //freopen("output.txt","w",stdout); 93 n=read();m=read(); 94 for1(i,n)v[i]=sum[i]=read(); 95 while(m--){ 96 int ch=read(),x=read(),y=read(); 97 if(ch==1)link(x,y); 98 else if(ch==2)cut(x,y); 99 else if(ch==3)makeroot(x),v[x]=y,pushup(x); 100 else if(x==y)printf("%d\n",v[x]); 101 else split(x,y),printf("%d\n",sum[y]); 102 } 103 return 0; 104 }