Submit: 1764 Solved: 785
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
Source
LCT裸题
喜闻乐见1A
再跟自己说一遍:把x变为树根的时候rev不会影响到右子树是因为x的右子树在access的时候已经断掉了! ←每次写LCT都要在这里犯迷糊也是够了
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=301115; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 struct node{ 17 int ch[2],fa; 18 int val,smm; 19 bool rev; 20 }t[mxn]; 21 inline bool isroot(const int x){return (t[t[x].fa].ch[0]!=x && t[t[x].fa].ch[1]!=x);} 22 void pushup(int x){ 23 int lc=t[x].ch[0],rc=t[x].ch[1]; 24 // printf("x:%d lc:%d %d rc:%d %d ",x,lc,t[lc].smm,rc,t[rc].smm); 25 t[x].smm=t[lc].smm^t[rc].smm^t[x].val; 26 return; 27 } 28 void PD(int x){ 29 if(t[x].rev){ 30 t[t[x].ch[0]].rev^=1; 31 t[t[x].ch[1]].rev^=1; 32 swap(t[x].ch[0],t[x].ch[1]); 33 t[x].rev^=1; 34 } 35 return; 36 } 37 void rotate(int &x){ 38 int y=t[x].fa,z=t[y].fa,lc,rc; 39 if(t[y].ch[0]==x)lc=0;else lc=1; rc=lc^1; 40 if(!isroot(y)){t[z].ch[t[z].ch[1]==y]=x;} 41 t[x].fa=z;t[y].fa=x; 42 t[y].ch[lc]=t[x].ch[rc]; 43 t[t[x].ch[rc]].fa=y; 44 t[x].ch[rc]=y; 45 pushup(y); 46 return; 47 } 48 int st[mxn],top=0; 49 void Splay(int &x){ 50 top=0;st[++top]=x; 51 for(int i=x;!isroot(i);i=t[i].fa){st[++top]=t[i].fa;} 52 while(top)PD(st[top--]); 53 while(!isroot(x)){ 54 int y=t[x].fa,z=t[y].fa; 55 if(!isroot(y)){ 56 if((t[z].ch[0]==y)^(t[y].ch[0]==x))rotate(x); 57 else rotate(y); 58 } 59 rotate(x); 60 } 61 pushup(x); 62 return; 63 } 64 void access(int x){ 65 int y=0; 66 for(;x;x=t[x].fa){ 67 Splay(x); 68 t[x].ch[1]=y; 69 pushup(x); 70 y=x; 71 } 72 return; 73 } 74 void mkroot(int x){ 75 access(x);Splay(x); 76 t[x].rev^=1; 77 return; 78 } 79 int find(int x){ 80 access(x);Splay(x); 81 while(t[x].ch[0])x=t[x].ch[0]; 82 return x; 83 } 84 void link(int x,int y){ 85 mkroot(x); 86 t[x].fa=y; 87 return; 88 } 89 void cut(int x,int y){ 90 mkroot(x);access(y);Splay(y); 91 if(t[y].ch[0]==x){t[y].ch[0]=0;t[x].fa=0;} 92 return; 93 } 94 int query(int x,int y){ 95 mkroot(x); 96 access(y);Splay(y); 97 return t[y].smm; 98 } 99 int n,m; 100 int main(){ 101 // freopen("in.txt","r",stdin); 102 int i,j; 103 n=read();m=read(); 104 for(i=1;i<=n;i++){ 105 // t[i].fa=i; //Wrong! 106 t[i].smm=t[i].val=read(); 107 } 108 int u,v,op; 109 while(m--){ 110 op=read();u=read();v=read(); 111 switch(op){ 112 case 0:{ 113 printf("%d ",query(u,v)); 114 break; 115 } 116 case 1:{ 117 if(find(u)!=find(v))link(u,v); 118 break; 119 } 120 case 2:{ 121 if(find(u)==find(v))cut(u,v); 122 break; 123 } 124 case 3:{ 125 access(u); Splay(u); 126 t[u].val=v; 127 pushup(u); 128 break; 129 } 130 } 131 } 132 return 0; 133 }