LCT学习笔记

一.每棵splay中的中序遍历都是原树上深度严格递增的点

二.原树上x与y有边,在LCT上有两种可能,所以fa[x]也有两种不同的含义

1.在同一颗splay中,那么之间就没有边的关系了,换句话说不一定相邻,但可以根据性质一来找出
此时的fa[x]指的是splay中的fa

2.在不同的splay中,那么x所在的splay的根节点会有一条连向y的边,
具体形式为fa[rt_x]=y(认父不认子),可以发现此时x一定是当前splay中深度最小的点(因为它有父亲)
所以如果一颗splay的根节点有指出去的边fa[rt],那么这条边的主人一定是这颗splay中深度最小的点
此时的fa[x]指的是两颗splay间的边
void link(int x,int y)
{
	access(x);
	splay(x);
	fa[x]=y;
}

四.Cut

access(x)后可以发现,x是新splay中深度最大的点,x的父亲y是深度次大的点,我们只需将x和其余点断开即可,并不需要将y splay成x的左儿子
void cut(int x,int y)
{
	access(x);
	splay(x);
	fa[ch[x][0]]=0;
	ch[x][0]=0;
}

五.Findroot

int findroot(int x)
{
	access(x);
	splay(x);
	while(ch[x][0])
	{
		pushdown(x);
		x=ch[x][0];
	}
	splay(x);
	return x;
}

以上为有根树的做法,不用查询x到y的路径信息,只需要查询x到根节点的路径信息,就可以这样做。

但如果要查询x到y的路径信息,那么就需要makeroot,将y变成树的根,然后就可以用查询x到根节点的路径信息的做法了

六.Makeroot

access(x)后x是新splay中深度最大的点,我们直接交换x的左右儿子,就能完成将x变成splay中深度最小的点
void makeroot(int x)
{
	access(x);
	splay(x);
	pushR(x);
}

七.新Link和Cut

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&&ch[y][0]==0)
	{
		fa[y]=ch[x][1]=0;
		pushup(x);
	}
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务