bzoj 3282 Tree
3282: Tree
Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1256 Solved: 549
[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和。
lct裸题。注意只要修改了儿子操作后要update,splay上的fa不代表是树中的fa,应该makeroot在access看他们是否成父子关系
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define maxn 3000020 7 8 int child[maxn][2],fa[maxn],sum[maxn],rev[maxn],key[maxn]; 9 int n,m,stack[maxn],tops = -1; 10 11 inline bool isroot(int x){ 12 return (child[fa[x]][0] != x && child[fa[x]][1] != x); 13 } 14 inline void reverse(int x){ 15 rev[x] ^= 1; 16 swap(child[x][0],child[x][1]); 17 } 18 inline void pushdown(int x){ 19 if ( rev[x] ){ 20 if ( child[x][0] ) reverse(child[x][0]); 21 if ( child[x][1] ) reverse(child[x][1]); 22 rev[x] = 0; 23 } 24 } 25 inline void update(int x){ 26 sum[x] = key[x] ^ sum[child[x][0]] ^ sum[child[x][1]]; 27 } 28 inline void rotate(int x){ 29 int t = child[fa[x]][1] == x; 30 int y = fa[x] , z = child[x][1 - t]; 31 fa[x] = fa[y]; 32 if ( !isroot(y) ) child[fa[y]][child[fa[y]][1] == y] = x; 33 fa[y] = x; 34 child[x][1 - t] = y; 35 if ( z ){ 36 fa[z] = y; 37 } 38 child[y][t] = z; 39 update(y); 40 } 41 inline void splay(int x){ 42 stack[++tops] = x; 43 for (int i = x ; !isroot(i) ; i = fa[i]) stack[++tops] = fa[i]; 44 while ( ~tops ) pushdown(stack[tops--]); 45 while ( !isroot(x) ){ 46 int y = fa[x] , z = fa[y]; 47 if ( !((child[y][0] == x) ^ (child[z][0] == y)) && !isroot(y) ) rotate(y); 48 else rotate(x); 49 if ( isroot(x) ) break; 50 rotate(x); 51 } 52 update(x); 53 } 54 inline void access(int x){ 55 int t = 0; 56 for (;x;x = fa[x]) 57 splay(x) , child[x][1] = t ,update(x), t = x; 58 } 59 inline void makeroot(int x){ 60 access(x); 61 splay(x); 62 reverse(x); 63 } 64 inline int findroot(int x){ 65 access(x); 66 splay(x); 67 // pushdown(x); 在splay时已经pushdown过了 68 while ( child[x][0] ) x = child[x][0]; //pushdown(x); 69 return x; 70 } 71 inline void link(int x,int y){ 72 makeroot(y); 73 fa[y] = x; 74 } 75 inline void cut(int x,int y){ 76 makeroot(x); 77 access(y); 78 splay(y); 79 if ( child[y][0] == x ) child[y][0] = fa[x] = 0; 80 else if ( child[y][1] == x ) child[y][1] = fa[x] = 0; 81 update(y); 82 } 83 void print(){ 84 for (int i = 1 ; i <= n ; i++) cout<<i<<" fa "<<fa[i]<<" child "<<child[i][0]<<" "<<child[i][1]<<endl; 85 } 86 int main(){ 87 freopen("input.txt","r",stdin); 88 scanf("%d %d",&n,&m); 89 for (int i = 1 ; i <= n ; i++) scanf("%d",&sum[i]) , key[i] = sum[i]; 90 for (int i = 1 ; i <= m ; i++){ 91 int x,y,t; 92 scanf("%d %d %d",&t,&x,&y); 93 if ( t == 0 ){ 94 makeroot(x); 95 access(y); 96 splay(y); 97 printf("%d\n",sum[y]); 98 } 99 else if ( t == 1 ){ 100 if ( findroot(x) != findroot(y) ){ 101 link(x,y); 102 } 103 } 104 else if ( t == 2 ){ 105 cut(x,y); 106 } 107 else if ( t == 3 ){ 108 splay(x); 109 key[x] = y; 110 update(x); 111 } 112 } 113 return 0; 114 }