【BZOJ3282】Tree LCT

1A爽,感觉又对指针重怀信心了呢= =,模板题,注意单点修改时splay就好,其实按吾本意是没写的也A了,不过应该加上能更好维护平衡性。

。。还是得加上好= =

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #define N 300010
  4 using namespace std;
  5 int n,m;
  6 struct node
  7 {
  8     node *fa,*ch[2];
  9     int xor_sum,data;
 10     bool rev;
 11     node(int x);
 12     bool chr() {return this==fa->ch[1];}
 13     bool isrt() {return this!=fa->ch[1] && this!=fa->ch[0];}
 14     void setc(node *x,int t) {this->ch[t]=x; x->fa=this;}
 15     void push_up()    {xor_sum=ch[0]->xor_sum^ch[1]->xor_sum^data;}
 16     void push_down() 
 17     {
 18         if (!isrt()) fa->push_down();
 19         if (rev)
 20         {
 21             ch[1]->rev^=1;
 22             ch[0]->rev^=1;
 23             swap(ch[0],ch[1]);
 24             rev=0;
 25         } 
 26     }
 27 }*null=new node(0),*lct[N];
 28 node::node(int x)
 29 {
 30     fa=ch[1]=ch[0]=null;
 31     data=xor_sum=x;
 32     rev=0;
 33 }
 34 inline int read()
 35 {
 36     int ans=0,f=1;
 37     char c;
 38     while (!isdigit(c=getchar())){if (c=='-') f=-1;}
 39     ans=c-'0';
 40     while (isdigit(c=getchar())) ans=ans*10+c-'0';
 41     return ans*f;
 42 }
 43 namespace LCT
 44 {
 45     void rotate(node *x)
 46     {
 47         node *r=x->fa;
 48         int t=x->chr();
 49         if (x==null || r==null) return;
 50         //x->push(); y->push();
 51         if (r->isrt()) x->fa=r->fa;
 52         else r->fa->setc(x,r->chr());
 53         r->setc(x->ch[t^1],t);
 54         x->setc(r,!t);
 55         x->push_up(); r->push_up();
 56     }
 57     void splay(node *x)
 58     {
 59         x->push_down();
 60         for (;!x->isrt();rotate(x))
 61             if (!x->fa->isrt())
 62                 if (x->chr()==x->fa->chr()) rotate(x->fa);
 63                 else rotate(x);
 64         x->push_up();
 65     }
 66     void Access(node *x)
 67     {
 68         node *y=null;
 69         for (;x!=null;y=x,x=x->fa)
 70         {
 71             splay(x);
 72             x->ch[1]=y;
 73         }
 74     }
 75     void MakeRoot(node *x)
 76     {
 77         Access(x); splay(x); x->rev^=1;
 78     }
 79     void Link(node *x,node *y)
 80     {
 81         MakeRoot(x); //Access(y); splay(y);
 82         x->fa=y;
 83     }
 84     void Cut(node *x,node *y)
 85     {
 86         MakeRoot(x); Access(y); splay(y);
 87         y->ch[0]->fa=null; y->ch[0]=null;
 88     }
 89     node *Findfa(node *x)
 90     {
 91         Access(x); splay(x);
 92         while (x->ch[0]!=null) x=x->ch[0];
 93         return x;
 94     }
 95     void Change(node *x,int v)
 96     {
 97         x->push_down();
 98         splay(x);
 99         x->data=v;
100         x->push_up();
101     }
102     int Query(node *x,node *y)
103     {
104         MakeRoot(x);
105         Access(y);
106         splay(y);
107         return y->xor_sum;
108     }
109 }
110 using namespace LCT;
111 int main()
112 {
113     int temp,x,y;
114     n=read();
115     m=read();
116     for (int i=1;i<=n;i++) x=read(),lct[i]=new node(x);
117     for (int i=1;i<=m;i++)
118     {
119         temp=read(); x=read(); y=read();
120         switch (temp)
121         {
122             case 0:printf("%d\n",LCT::Query(lct[x],lct[y])); break;
123             case 1:if (Findfa(lct[x])!=Findfa(lct[y])) Link(lct[x],lct[y]); break;
124             case 2:if (Findfa(lct[x])==Findfa(lct[y])) Cut(lct[x],lct[y]); break; 
125             case 3:Change(lct[x],y); break;
126         }
127     }
128     return 0;
129 }
View Code

 


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

Sample Output

3
1

HINT

 

1<=N,M<=300000

 

Source

posted @ 2016-03-27 15:37  DMoon  阅读(182)  评论(0编辑  收藏  举报