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 }