1. 程式人生 > >luoguP3690 【模板】Link Cut Tree (動態樹)[LCT]

luoguP3690 【模板】Link Cut Tree (動態樹)[LCT]

格式 %d getch logs cstring name flag -1 處理

題目背景

動態樹

題目描述

給定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 }

luoguP3690 【模板】Link Cut Tree (動態樹)[LCT]