Link Cut Tree
题目背景
动态树
题目描述
给定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$ \leq $ N,M $ \leq $ 3 · $ 10^5 $
分析:
Link Cut Tree模板题。具体的知识点这位大佬已经讲的特别好了,推荐这位大佬的博客<http://www.cnblogs.com/flashhu/p/8324551.html>,蒟蒻就只放代码了。
Code:
1 //It is made by HolseLee on 27th June 2018 2 //Luogu.org P3690 3 #include<bits/stdc++.h> 4 using namespace std; 5 const int N=3e5+7; 6 int n,m,val[N]; 7 struct LCT{ 8 int fa[N],ch[N][2],xr[N],sign[N],q[N],top; 9 inline void pushup(int u) 10 { 11 xr[u]=xr[ch[u][0]]^xr[ch[u][1]]^val[u]; 12 } 13 inline void change(int u) 14 { 15 int temp=ch[u][0]; 16 ch[u][0]=ch[u][1]; 17 ch[u][1]=temp; 18 sign[u]^=1; 19 } 20 inline void pushdown(int u) 21 { 22 if(!sign[u])return; 23 if(ch[u][0])change(ch[u][0]); 24 if(ch[u][1])change(ch[u][1]); 25 sign[u]=0; 26 } 27 inline bool isroot(int u) 28 { 29 return (ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u); 30 } 31 inline void rotate(int x) 32 { 33 int y=fa[x],z=fa[y]; 34 int k=(ch[y][1]==x); 35 int w=ch[x][k^1]; 36 if(!isroot(y))ch[z][ch[z][1]==y]=x; 37 ch[x][k^1]=y;ch[y][k]=w; 38 if(w)fa[w]=y;fa[y]=x;fa[x]=z; 39 pushup(y);pushup(x); 40 } 41 inline void splay(int x) 42 { 43 top=1;q[top]=x; 44 for(int i=x;!isroot(i);i=fa[i]) 45 q[++top]=fa[i]; 46 while(top)pushdown(q[top--]); 47 while(!isroot(x)){ 48 int y=fa[x],z=fa[y]; 49 if(!isroot(y)) 50 (ch[y][0]==x)^(ch[z][0]==y)?rotate(x):rotate(y); 51 rotate(x); 52 } 53 } 54 void access(int u) 55 { 56 for(int i=0;u;i=u,u=fa[u]){ 57 splay(u);ch[u][1]=i;pushup(u);} 58 } 59 void makeroot(int u) 60 { 61 access(u);splay(u);change(u); 62 } 63 inline int find(int u) 64 { 65 access(u);splay(u); 66 while(ch[u][0])pushdown(u),u=ch[u][0]; 67 splay(u); 68 return u; 69 } 70 void split(int u,int v) 71 { 72 makeroot(u);access(v);splay(v); 73 } 74 void cut(int u,int v) 75 { 76 makeroot(u); 77 if(find(v)==u&&fa[v]==u&&!ch[v][0]){ 78 fa[v]=ch[u][1]=0;pushup(u);} 79 } 80 void link(int u,int v) 81 { 82 makeroot(u); 83 if(find(v)!=u)fa[u]=v; 84 } 85 }T; 86 inline int read() 87 { 88 char ch=getchar();int num=0;bool flag=false; 89 while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();} 90 while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();} 91 return flag?-num:num; 92 } 93 int main() 94 { 95 n=read();m=read();int opt,x,y; 96 for(int i=1;i<=n;i++){ 97 val[i]=read();T.xr[i]=val[i];} 98 for(int i=1;i<=m;i++){ 99 opt=read();x=read();y=read(); 100 if(opt==0){ 101 T.split(x,y); 102 printf("%d\n",T.xr[y]);} 103 else if(opt==1){T.link(x,y);} 104 else if(opt==2){T.cut(x,y);} 105 else if(opt==3){ 106 T.splay(x);val[x]=y;T.pushup(x);} 107 } 108 return 0; 109 }