一.每棵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间的边
三.Link
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);
}
}