P3690-[模板]Link Cut Tree(动态树)【Splay】

正题

题目链接:https://www.luogu.org/problem/P3690


题目大意

n n n个点 m m m个操作,要求支持

  1. 询问路径异或和
  2. 连接一条边(若 x , y x,y x,y没联通)
  3. 删除一条边
  4. 修改一个点的权值

解题思路

L C T LCT LCT板子题不解释。


c o d e code code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e5+100;
int n,m,v[N];
struct Link_Cut_Tree{
	int w[N],fa[N],son[N][2];
	bool r[N];
	#define ls son[x][0]
	#define rs son[x][1]
	bool nroot(int x)
	{return son[fa[x]][0]==x||son[fa[x]][1]==x;}
	void PushUp(int x)
	{w[x]=w[ls]^w[rs]^v[x];return;}
	void PushR(int x)
	{swap(ls,rs);r[x]^=1;return;}
	void PushDown(int x){
		if(r[x]){
			if(ls) PushR(ls);
			if(rs) PushR(rs);
			r[x]=0;
		}
		return;
	}
	void Rotate(int x){
		int y=fa[x],z=fa[y],k=(son[y][1]==x),w=son[x][!k];
		if(nroot(y)) son[z][son[z][1]==y]=x;
		son[x][!k]=y;son[y][k]=w;
		if(w) fa[w]=y;fa[y]=x;fa[x]=z;
		PushUp(y);return;
	}
	void PushHall(int x){
		if(nroot(x)) PushHall(fa[x]);
		PushDown(x); return;
	}
	void Splay(int x){
		int y=x,z=0;
		PushHall(x);
		while(nroot(x)){
			y=fa[x];z=fa[y];
			if(nroot(y))
				Rotate((son[y][0]==x)^(son[z][0]==y)?x:y);
			Rotate(x);
		} 
		PushUp(x);
		return;
	}
	void Access(int x){
		for(int y=0;x;x=fa[y=x])
			Splay(x),rs=y,PushUp(x);
		return;
	}
	void MakeRoot(int x)
	{Access(x);Splay(x);PushR(x);return;}
	int FindRoot(int x){
		Access(x);Splay(x);
		while(ls) PushDown(x),x=ls;
		Splay(x);return x;
	}
	void Split(int x,int y)
	{MakeRoot(x);Access(y);Splay(y);return;}
	void Link(int x,int y)
	{
		MakeRoot(x);
		if(FindRoot(y)!=x) fa[x]=y;
	}
	void Cut(int x,int y)
	{
		MakeRoot(x);
		if(FindRoot(y)==x&&fa[y]==x&&!son[y][0]){
			fa[y]=son[x][1]=0;
			PushUp(x);
		} 
	}
	#undef ls
	#undef rs
}LCT;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&v[i]);
	while(m--){
		int op,x,y;
		scanf("%d%d%d",&op,&x,&y);
		if(op==0){LCT.Split(x,y);printf("%d\n",LCT.w[y]);}
		if(op==1){LCT.Link(x,y);}
		if(op==2){LCT.Cut(x,y);}
		if(op==3){LCT.Splay(x);v[x]=y;}
	}
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值