Link-Cut Tree动态树模板

讲解博客:https://www.cnblogs.com/zhoushuyu/p/8137553.html 

struct Link_Cut_Tree
{
	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;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Frozen_Guardian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值