洛谷P3690 [模板] Link Cut Tree [LCT]

  题目传送门

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:  复制
3 3 
1
2
3
1 1 2
0 1 2 
0 1 1
输出样例#1:  复制
3
1

说明

数据范围: 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 } 

猜你喜欢

转载自www.cnblogs.com/cytus/p/9236383.html
今日推荐