1. 程式人生 > >洛谷P3690 [模板] Link Cut Tree [LCT]

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

con radi 復制 blank clas microsoft 博客 push ()

  題目傳送門

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 }

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