luoguP3690 【模板】Link Cut Tree (动态树)[LCT]

题目背景

动态树

题目描述

给定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。

输入输出格式

输入格式:

第1行两个整数,分别为N和M,代表点数和操作数。

第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。

第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。

输出格式:

对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。

输入输出样例

输入样例#1:
3 3 
1
2
3
1 1 2
0 1 2 
0 1 1
输出样例#1:
3
1

说明

数据范围: 


 

因为只是模板题吧。。在这里直接放上代码。。

关于LCT可以看论文:QTREE解法的一些研究

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 using namespace std;
  5 
  6 int read(){
  7     char ch;
  8     int re=0;
  9     bool flag=0;
 10     while((ch=getchar())!='-'&&(ch<'0'||ch>'9'));
 11     ch=='-'?flag=1:re=ch-'0';
 12     while((ch=getchar())>='0'&&ch<='9')  re=re*10+ch-'0';
 13     return flag?-re:re;
 14 }
 15 
 16 struct Splay{
 17     int ch[2],xr,fa;
 18     bool rev;
 19 };
 20 
 21 const int maxn=300005;
 22 
 23 int n,m,top;
 24 int val[maxn],stk[maxn];
 25 Splay T[maxn];
 26 
 27 inline void push_up(int x){  T[x].xr=T[T[x].ch[0]].xr^T[T[x].ch[1]].xr^val[x];   }
 28 
 29 inline bool isroot(int x){
 30     return T[T[x].fa].ch[0]!=x&&T[T[x].fa].ch[1]!=x;
 31 }
 32 
 33 inline void push_down(int x){
 34     if(T[x].rev){
 35         T[T[x].ch[0]].rev^=1;
 36         T[T[x].ch[1]].rev^=1;
 37         swap(T[x].ch[0],T[x].ch[1]);
 38         T[x].rev=0;
 39     }
 40 }
 41 
 42 void rot(int x){
 43     int y=T[x].fa,z=T[y].fa,l,r;
 44     if(T[y].ch[0]==x)  l=0;
 45     else  l=1;
 46     r=l^1;
 47     T[x].fa=z;
 48     if(!isroot(y))  T[z].ch[T[z].ch[1]==y]=x;
 49     T[T[x].ch[r]].fa=y;
 50     T[y].ch[l]=T[x].ch[r];
 51     T[y].fa=x;
 52     T[x].ch[r]=y;
 53     push_up(y),push_up(x);
 54 }
 55 
 56 void splay(int x){
 57     top=1;  stk[top]=x;
 58     for(int i=x;!isroot(i);i=T[i].fa)  stk[++top]=T[i].fa;
 59     for(int i=top;i;i--)  push_down(stk[i]);
 60     while(!isroot(x)){
 61         int y=T[x].fa,z=T[y].fa;
 62         if(!isroot(y)){
 63             if((T[y].ch[0]==x)^(T[z].ch[0]==y))  rot(x);
 64             else  rot(y);
 65         }
 66         rot(x);
 67     }
 68 }
 69 
 70 void acc(int x){
 71     int t=0;
 72     while(x){
 73         splay(x);
 74         T[x].ch[1]=t;
 75         push_up(x);
 76         t=x;  x=T[x].fa;
 77     }
 78 }
 79 
 80 void make_root(int x){
 81     acc(x);
 82     splay(x);
 83     T[x].rev^=1;
 84 }
 85 
 86 int find(int x){
 87     acc(x);
 88     splay(x);
 89     while(T[x].ch[0])  x=T[x].ch[0];
 90     return x;
 91 }
 92 
 93 void split(int x,int y){
 94     make_root(x);
 95     acc(y);
 96     splay(y);
 97 }
 98 
 99 void cut(int x,int y){
100     split(x,y);
101     if(T[y].ch[0]==x)  T[y].ch[0]=0,T[x].fa=0;
102 }
103 
104 void link(int x,int y){
105     make_root(x);
106     T[x].fa=y;
107 }
108 
109 int main(){
110 //    freopen("temp.in","r",stdin);
111     n=read(),m=read();
112     for(int i=1;i<=n;i++){
113         val[i]=read();
114         T[i].xr=val[i];
115     }
116     int opt,x,y,xx,yy;
117     while(m--){
118         opt=read(),x=read(),y=read();
119         switch(opt){
120             case 0:{
121                 split(x,y);
122                 printf("%d\n",T[y].xr);
123                 break;
124             }
125             case 1:{
126                 xx=find(x),yy=find(y);
127                 if(xx!=yy)  link(x,y);
128                 break;
129             }
130             case 2:{
131                 xx=find(x),yy=find(y);
132                 if(xx==yy)  cut(x,y);
133                 break;
134             }
135             case 3:{
136                 acc(x);
137                 splay(x);
138                 val[x]=y;
139                 push_up(x);
140                 break;
141             }
142         }
143     }
144     return 0;
145 }

 

posted @ 2017-08-16 22:04  ZYBGMZL  阅读(226)  评论(0编辑  收藏  举报