洛谷 - P3690 【模板】Link Cut Tree (動態樹)(LCT模板)
題目連結:點選檢視
題目大意:給出 n 個帶權節點,需要執行 m 次操作,每次操作分為四種型別:
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。
題目分析:直接呼叫相應的函式即可
程式碼:
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=3e5+100;
int val[N];
struct LCT
{
int fa[N],ch[N][2],sum[N],rev[N],Stack[N],top;
bool son(int x)//判斷點x是父節點的左兒子還是右兒子
{
return x==ch[fa[x]][1];
}
bool isroot(int x)//判斷一個點是不是根節點(當前splay的根節點)
{
return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
}
void pushup(int x)//上傳(維護資訊)
{
sum[x]=sum[ch[x][0]]^sum[ch[x][1]]^val[x];
}
void reverse(int x)//交換左右子樹
{
if(!x)return;
swap(ch[x][0],ch[x][1]);rev[x]^=1;
}
void pushdown(int x)//下傳(更新反轉標記用)
{
if(!rev[x])return;
reverse(ch[x][0]);reverse(ch[x][1]);
rev[x]=0;
}
void rotate(int x)//splay的旋轉
{
int y=fa[x],z=fa[y],c=son(x);
ch[y][c]=ch[x][c^1];if(ch[y][c]) fa[ch[y][c]]=y;
fa[x]=z;if(!isroot(y))ch[z][son(y)]=x;
ch[x][c^1]=y;fa[y]=x;pushup(y);
}
void splay(int x)//將x轉到根節點
{
Stack[top=1]=x;
for (int i=x;!isroot(i);i=fa[i])
Stack[++top]=fa[i];
while (top) pushdown(Stack[top--]);
for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
if (!isroot(y)) son(x)^son(y)?rotate(x):rotate(y);
pushup(x);
}
void access(int x)//把x節點到x所在樹(連通塊)的根節點之間的路徑全部變成重路徑
{
for (int y=0;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,pushup(x);
}
void makeroot(int x)//把x節點設為x所在樹(連通塊)的根節點
{
access(x);splay(x);reverse(x);
}
int findroot(int x)//找到x節點所在樹(連通塊)的根節點
{
access(x);splay(x);
while (ch[x][0]) x=ch[x][0];
splay(x);return x;
}
void split(int x,int y)//摳出x到y的路徑,摳完以後y是splay的根
{
makeroot(x);access(y);splay(y);
}
void cut(int x,int y)//砍斷x到y的邊
{
makeroot(x);
if(findroot(y)==x&&fa[y]==x&&!ch[y][0])
fa[y]=ch[x][1]=0,pushup(x);
}
void link(int x,int y)//連線x到y的邊
{
makeroot(x);
if(findroot(y)!=x)fa[x]=y;
}
}t;
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",val+i);
while(m--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==0)
{
t.split(x,y);
printf("%d\n",t.sum[y]);
}
else if(op==1)
{
t.link(x,y);
}
else if(op==2)
{
t.cut(x,y);
}
else if(op==3)
{
t.splay(x);
val[x]=y;
}
}
return 0;
}
相關文章
- 動態主席樹模板
- LCT模板(無講解)
- 洛谷題單指南-線段樹-P3373 【模板】線段樹 2
- Link Cut Tree學習筆記筆記
- 洛谷 P3919 可持久化線段樹 1 之主席樹模板(初級)持久化
- [學習筆記 #7] Link Cut Tree筆記
- 洛谷 P3388 【模板】割點(割頂)
- 洛谷P2613 【模板】有理數取餘
- 靜態主席樹模板
- 洛谷P3383 【模板】線性篩素數
- 洛谷題單指南-二叉堆與樹狀陣列-P3378 【模板】堆陣列
- 洛谷題單指南-集合-P3370 【模板】字串雜湊字串
- 演算法學習筆記(16):Link Cut Tree演算法筆記
- 洛谷題單指南-二叉堆與樹狀陣列-P3368 【模板】樹狀陣列 2陣列
- 洛谷 - P6292 區間本質不同子串個數(SAM+LCT+線段樹)
- 模板 - 動態規劃動態規劃
- 洛谷題單指南-分治與倍增-P1226 【模板】快速冪
- 主席樹模板
- freemarker根據靜態模板和動態模板生成PDF與Word
- 洛谷題單指南-分治與倍增-P1177 【模板】歸併排序排序
- 劃分樹模板+模板題--hdu4251
- 洛谷P1087 FBI樹
- 洛谷-P1250 種樹
- 線段樹模板
- 洛谷P3285 [SCOI2014]方伯伯的OJ 動態開點平衡樹
- 「 洛谷 」P4539 [SCOI2006]zh_tree
- 【模板】最小生成樹
- 【模板】珂朵莉樹
- 洛谷P4781 【模板】拉格朗日插值(拉格朗日插值)
- 洛谷題單指南-常見最佳化技巧-P1886 滑動視窗 /【模板】單調佇列佇列
- 【線段樹提高】51nod &&洛谷
- 洛谷P3369 普通平衡樹(Splay)
- 如何在Final Cut Pro X中安裝fcpx模板
- 洛谷P4197 Peaks(Kruskal重構樹 主席樹)
- 洛谷 P3366 【模板】最小生成樹(並查集+壓縮路徑(縮短到最高上一級的步驟))並查集
- Excel模板匯出之動態匯出Excel
- 模板口胡:樹同構
- P8306 【模板】字典樹