【BZOJ】【3282】Tree
LCT
喜闻乐见的Link-Cut-Tree……
srO zyf
http://www.cnblogs.com/zyfzyf/p/4149109.html
目测我是第222个?………………不要在意这些细节……
和以前写的splay还是有些区别呢……
比如splay中Push_down的写法……还有rotate的新姿势~
算法看看论文什么的……很好懂
1 /************************************************************** 2 Problem: 3282 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:2596 ms 7 Memory:8596 kb 8 ****************************************************************/ 9 10 //BZOJ 3282 11 #include<cstdio> 12 #include<vector> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 #define pb push_back 21 using namespace std; 22 const int N=300010; 23 #define debug 24 25 int c[N][2],fa[N],v[N],s[N],st[N],top=0; 26 bool rev[N]; 27 int n,m; 28 29 void Push_up(int x){ 30 int l=c[x][0],r=c[x][1]; 31 s[x]=s[l]^s[r]^v[x]; 32 } 33 void Push_down(int x){ 34 int l=c[x][0],r=c[x][1]; 35 if(rev[x]){ 36 rev[x]^=1; rev[l]^=1; rev[r]^=1; 37 swap(c[x][0],c[x][1]); 38 } 39 } 40 bool isroot(int x){ 41 return c[fa[x]][0]!=x && c[fa[x]][1]!=x; 42 } 43 void rotate(int x){ 44 int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; 45 if (!isroot(y)) c[z][c[z][1]==y]=x; 46 fa[x]=z; fa[y]=x; fa[c[x][r]]=y; 47 c[y][l]=c[x][r]; c[x][r]=y; 48 Push_up(y); Push_up(x); 49 } 50 void splay(int x){ 51 top=0; st[top++]=x; 52 for(int i=x;!isroot(i);i=fa[i]) 53 st[top++]=fa[i]; 54 while(top--) Push_down(st[top]); 55 56 while(!isroot(x)){ 57 int y=fa[x],z=fa[y]; 58 if (!isroot(y)){ 59 if (c[y][0]==x^c[z][0]==y) rotate(x); 60 else rotate(y); 61 } 62 rotate(x); 63 } 64 } 65 void access(int x){ 66 for(int t=0;x;t=x,x=fa[x]) 67 splay(x),c[x][1]=t,Push_up(x); 68 } 69 void makeroot(int x){ 70 access(x); splay(x); rev[x]^=1; 71 } 72 int find(int x){ 73 access(x); splay(x); 74 while(c[x][0]) x=c[x][0]; 75 return x; 76 } 77 void cut(int x,int y){ 78 makeroot(x); access(y); splay(y); 79 if (c[y][0]==x) c[y][0]=fa[x]=0; 80 } 81 void link(int x,int y){ 82 makeroot(x); fa[x]=y; 83 } 84 //LCT end 85 int main(){ 86 #ifndef ONLINE_JUDGE 87 freopen("file.in","r",stdin); 88 // freopen("file.out","w",stdout); 89 #endif 90 scanf("%d%d",&n,&m); 91 F(i,1,n) {scanf("%d",&v[i]); s[i]=v[i];} 92 93 int c,x,y; 94 F(i,1,m){ 95 scanf("%d%d%d",&c,&x,&y); 96 switch(c){ 97 case 0:makeroot(x); access(y); splay(y); printf("%d\n",s[y]);break; 98 case 1:if (find(x)!=find(y)) link(x,y);break; 99 case 2:if (find(x)==find(y)) cut(x,y);break; 100 case 3:access(x); splay(x); v[x]=y; Push_up(x);break; 101 } 102 } 103 return 0; 104 }
3282: Tree
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 829 Solved: 342
[Submit][Status][Discuss]
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