bzoj 3282 Tree

3282: Tree

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 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 }

 

posted @ 2016-03-22 22:52  zhangqingqi  阅读(130)  评论(0编辑  收藏  举报