LCT的扩展操作

声明:本文大部分参考neither_nor‘s Blog,语言风格是博主按照自己的设定修改的

LCT可以支持关于点权和链的修改,换根,LINK,CUT和查询链信息操作,
然而有句话说得好:这世上本没有路,走的人多了,也便成了路(是树人老爷子的至理名言)
随着时代的发展,毒瘤出题人越来越多,
为了适应这样新的环境,神犇们就想出了一些diao的不行的方法
这里我们要讲解的就是LCT的另外一些NB操作

LCT,学名Link Cut Tree
基础知识这里就不在赘述了

知识铺垫

杨哲的集训队作业《QTREE解法的一些研究》

首先我们要明确一棵LCT到底是怎么维护信息的:

LCT的扩展操作_第1张图片

我们可以发现,我们在expose一个结点之后(如图,假如我们expose的是4)

该点的所有虚边所连的点集就是该点的在原树上的子树(除该点本身的信息)

所以我们是可以利用这一个性质的

子树信息:

对于一个点x,如果我们对x进行expose操作

那么ta的虚子树内将包含且仅包含 ta原树中子树内除了ta自己以外的所有点

如果我们维护了ta的虚子树信息和,我们把这个信息与ta自己的信息合并,我们就得到了ta在原树中的子树信息
在下面的讨论中,我们发现我们可以同时维护一个点的虚子树信息和LCT子树信息来达到维护虚子树信息的目的

我们需要维护一个x的LCT子树的信息和

x的LCT子树的信息和就等于x的实儿子的LCT子树信息和加上x的虚子树的信息和加上x自己

在splay的update函数中就可以直接维护

考虑一个点的虚子树信息会在什么情况下发生改变:
一个点的虚子树信息改变,当且仅当进行link或者expose操作

在进行expose操作时,

我们会有更换一个点x的右儿子的操作,
这时我们要把x原来的右儿子的LCT子树信息加入x的虚子树信息,
把x的新的右儿子的LCT子树信息从x的虚子树信息中减去
(一定细细体会这句话蕴含的真理)

在进行link操作时,

我们会先把点x换到根上,然后连一条x到y的虚边
这时我们发现不仅y的虚子树信息需要加入x的LCT子树信息,y的所有祖先的LCT子树信息也需要更改
所以在进行link操作的时候我们需要makeroot(x)再makeroot(y)
我们把x的爸爸设成y,这样只要把x的LCT子树信息统计入y得虚子树信息中即可
(不要忘了update(y))

换根操作、cut操作和链修改操作并不影响我们上边的讨论

例题:bzoj4530:题解

边权信息

对于每个点,我们定义他的“前一条边”和“后一条边”
前一条边指的即是ta在原树中与父亲之间的边(可能不存在),而后一条边指的是在当前的链剖分下,与ta在同一条剖分链上的儿子与他之间的边(可能不存在)
例如上图中,1的前一条边与4的后一条边都是不存在的,而2的前一条边就是(1,2),后一条边是(2,4),5的前一条边就是(2,5)

对于每个点,维护ta的前一条边和后一条边是哪条,注意是维护是哪条边,而不是直接维护边权

考虑在什么情况下前一条边和后一条边会发生变化:

  • 翻转操作时,我们显然除了交换左右儿子还要交换前一条边和后一条边
  • link操作时,我们要把x的前一条边设成(x,y)
  • cut操作时,我们要把cut掉的两个点其中一个的前一条边设成“不存在”,另一个的后一条边设成“不存在”
  • access操作时,我们有更换x的右儿子的操作,即改变了当前的链剖分,
    所以x的后一条边理应变成他新的右儿子所在的splay里最左边的点的前一条边,
    而为了找到这一条边,我们还需要维护每个splay的第一条边和最后一条边,
    即最左边的点的前一条边和最右边的点的后一条边,
    为什么要维护最后一条边呢,因为在翻转的时候我们要交换这两个值

这样的话,我们对每个点维护他的splay子树所代表的链的边权信息和
注意一个splay所代表的链所包含的边只有那些两个端点都在这个splay里的边,
比如上图中2的前一条边是(2,1)并且2在4的splay子树里,但是4的splay子树所代表的链是不包含(2,1)的

考虑信息的合并:
如果一个点有左子树,那么他的前一条边的另一个端点一定在左子树里,
所以他的链信息和就要加上左子树的链信息和以及他的前一条边的信息,右子树亦然

我们考虑链修改操作:
与链信息合并类似,如果他有左儿子,那么更改他的前一条边的权值,右儿子亦然,然后对这个点打标

这样就完成了边权的维护

这边文章的内容很不好理解,
博主也是一知半解。。。

后记:
舒老师表示,LCT没有办法维护边权第k大
博主鼓励ta把这个作为ta的国家集训队论文课题

你可能感兴趣的:(LCT,知识储备)