首先要感谢一下FlashHu的博客,是它让我学会了LCT。
这题应该算是LCT维护子树信息的模板题了。这篇博客就讲一下怎么维护子树信息。如果会的大佬就直接看代码吧,看一眼就懂了。
首先LCT上一个有两种儿子,一种是实儿子,一种是虚儿子,实儿子只有一个很好维护,在辅助树splay中维护即可。那么虚儿子怎么搞?
其实也很简单,我们发现各种操作虚儿子只会改变一个,所以直接修改就行。这样听着很迷看一下代码就明白了了。
会修改儿子虚实的其实就几个操作,首先是LCT最重要的access操作。
//vir维护的是虚子树信息,sz是整个子树的信息
void access(int x) {
for (int y = 0; x; y = x, x = fa[x]) {
splay(x);
vir[x] += sz[son[x][1]];
son[x][1] = y;
vir[x] -= sz[son[x][1]];
}
}
连边link操作
我这里写的是给y一个虚儿子x。
void link(int x, int y) {
split(x,y);
vir[fa[x] = y] += sz[x];
push_up(y);
}
这题没有cut操作,但我还是写一下吧,也很类似。
void cut(int x, int y) {
split(x, y);
sz[y] -= sz[x];
son[y][0] = fa[x] = 0;
}
最后讲一下这题怎么查询。将x,ysplit出来然后x那一部分必然都是x的虚子树,y同理,将其虚子树大小加一再乘起来即可。
然后这题就切了qwq。为了篇幅看起来不要太长这里就不给ac代码了(以防代码比文字长看起来很没面子),如果有人需要拍可以在评论区里告知。