我仅一届平凡人LCT(LinkCutTree)可以看作是Splay树维护的树链剖分。我们可以在一个动态树(森林)上维护树链信息。
重链剖分与实链剖分
类比树链剖分的重链剖分:在Splay树的基础上,我们定义一条实边:
一个节点的孩子节点指向一个节点,这个孩子节点的fa指针也指向这个节点(即双向边)
相对性的,我们定义一条虚边
一个节点的孩子节点指向一个节点,这个孩子节点的fa指针不指向这个节点(即但向边)
我们把一个区块里的所有实边连接起来,构成一个Splay树。实链的顶部被称为这个splay树的根,在这种结构基础上。我们定义几种操作。
1.splay
和普通splay树一样,我们将一个点伸展到根节点
2.access
从一个节点x,将其到原树根节点建立一条全部都是实边的路径。
1.将该节点伸展至当前splay的根节点2.将虚边上这个点的右孩子连接上这个根节点(虚边实化)3.向上更新后继续向上伸展(对x的fa节点)
3.mkroot
给原树换根。我们可以想象,我们如果把一颗树的节点当成根节点,只要把此节点到原根节点的路径进行调换就ok了。所以我们执行:
1.对x进行access操作。此时,x变成该splay树的最右边的节点(因为我们在access操作时,每到虚边我们都把它的根节点连接到上个节点的右孩子)2.将x伸展至根节点(x此时必没有右孩子)3.整体反转(从x开始)这条实链
4.findroot
寻找该节点的splay树的根节点
1.对x进行access。2.伸展x至根节点(此时x的根节点在当前树的最左端)3.向左递归至最低4.伸展该节点至根节点(防止数据卡链)5.返回该节点
5.link
将x,y进行连边(操作1)
1.对x进行mkroot。2.判断y的splay树的根节点是否为x,如果是直接return3.将x的fa节点指向(建立虚边)
6.cut
对x,y进行断边(操作2)
1.对x进行mkroot。2.如果x,y不在一个树上,或者是x,y不是挨着的,直接return3.断双向边
7.split
把x,y的路径拆出来
1.对x进行mkroot2.对y进行access3.对y进行splay
经过这些操作,我们发现,y此时是根结点,且y没有右孩子,左孩子是x,此时就可以访问有关y的任何操作了。
至此基本思路讲完(真的醉了)。