Luogu3690 【模板】Link Cut Tree (动态树)
https://www.luogu.com.cn/problem/P3690
\(LCT\)
\(LCT\)需要通过\(Splay\)来维护,每一个\(Splay\)对应的是原树的一条链,\(Splay\)中父子关系与原树不同
\(Splay\)节点除了标记以外,维护的有:
\(ch_0:\)左儿子,代表原树中深度中深度比该节点小的节点(因为在链上,所以代表其祖先)
\(ch_1:\)右儿子,代表原树中深度中深度比该节点大的节点(因为在链上,所以代表其子孙)
\(f:\)父亲,对于在\(Splay\)中的非根节点,其\(f\)就是\(Splay\)中的父亲,对于在\(Splay\)中的根节点,其父亲就是这条链在原树中的父亲
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100005
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
#define fa(x) a[x].f
#define v(x) a[x].val
#define s(x) a[x].xsum
#define tag(x) a[x].lazy
#define id(x) ((ls(fa(x))==x)?0:1)
using namespace std;
int n,m,opt,x,y,q[N];
struct node
{
int ch[2],f,val,xsum;
bool lazy;
}a[N];
void update(int x)
{
s(x)=s(ls(x))^s(rs(x))^v(x);
}
void pushdown(int x)
{
if (!tag(x))
return;
tag(ls(x))^=1;
tag(rs(x))^=1;
swap(ls(x),rs(x));
tag(x)=0;
}
void connect(int x,int F,int son)
{
fa(x)=F;
a[F].ch[son]=x;
}
bool isrt(int x)
{
return ls(fa(x))!=x && rs(fa(x))!=x;
}
void rot(int x)
{
int y=fa(x),r=fa(y);
int yson=id(x),rson=id(y);
if (!isrt(y))
connect(x,r,rson); else
fa(x)=r;
connect(a[x].ch[yson^1],y,yson);
connect(y,x,yson^1);
update(y),update(x);
}
void splay(int x)
{
int g=x,k=0;
q[++k]=g;
while (!isrt(g))
{
g=fa(g);
q[++k]=g;
}
while (k)
pushdown(q[k--]);
while (!isrt(x))
{
int y=fa(x);
if (isrt(y))
rot(x); else
if (id(x)==id(y))
rot(y),rot(x); else
rot(x),rot(x);
}
}
void access(int x)
{
for (int y=0;x;y=x,x=fa(x))
{
splay(x);
rs(x)=y;
update(x);
}
}
void makeroot(int x)
{
access(x);
splay(x);
tag(x)^=1;
pushdown(x);
}
int findroot(int x)
{
access(x);
splay(x);
pushdown(x);
while (ls(x))
{
x=ls(x);
pushdown(x);
}
splay(x);
return x;
}
void split(int x,int y)
{
makeroot(x);
access(y);
splay(y);
}
void link(int x,int y)
{
makeroot(x);
if (findroot(y)==x)
return;
fa(x)=y;
}
void cut(int x,int y)
{
makeroot(x);
if (findroot(y)==x && fa(y)==x && !ls(y))
{
fa(y)=rs(x)=0;
update(x);
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&v(i)),s(i)=v(i);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&opt,&x,&y);
if (opt==0)
{
split(x,y);
printf("%d\n",s(y));
} else
if (opt==1)
link(x,y); else
if (opt==2)
cut(x,y); else
{
splay(x);
v(x)=y;
update(x);
}
}
return 0;
}