这是之前的总结,就是讲了一下基础。
基础题
LCT 适用于维护动态的题目,特别是有删边和加边操作的题目,如果题目明确说明需要删边和加边,那大概率就差把“LCT”写在题面里面了。
在写代码上有一个需要注意的地方就是 LCT 不是 leefy 的,所以 pushup 需要把当前节点的贡献也算上。
P3203 [HNOI2010] 弹飞绵羊
就是维护这个点到下一个能跳到点连边,如果跳出去连 ,最后看这个点到 的距离。
P1501 [国家集训队] Tree II
这道题就是模板的进阶,像线段树那样写 Tag 就好了。
P2173 [ZJOI2012] 网络
才开始读错题以为不一定是树,想着线段树分治+LCT。。。
对每个颜色开一个 LCT 就行了。最难受的是特判,颜色相同就不需要操作,直接输出 success。
维护序列关系
这一部分就跟线段树很想了,就是变了一下维护它的数据结构。写法反正我一般就是类似地使用结构体,就是需要注意很多细节,还有和模板的差异。
U684923 树上最长顺子
lsy 学长自己随手出的例题,放这里刚刚好。
像线段树那样,维护各种能表示区间的信息。
注意:初始化 c.ld = 0;c.rd = 0; 因为 有可能只有一个节点,后面赋值赋不到。
思路
需要维护的信息:区间长度,区间左右端点权值,最长前缀顺子长度(递增/递减),最长后缀顺子长度,区间内最长顺子长度。
于是我们可以根据 合并出 此时的状态和答案。
注意 pushdown 等标记的传送,还有反转操作的。
维护 MST
LCT 可以根据最小生成树的性质,也就是 Kruskal 证明的一些结论,进行最小生成树的维护。比如说我们加入一条边,需要找到这条边两个端点原路径上的边权最小值,看看能不能替换。如果能,就进行 LCT 的删边/加边操作。
P2387 [NOI2014] 魔法森林
这道题边权有两个维度,我们固定一维,然后计算另一维的最小值。我们枚举选取 ,然后一点点把在范围内的边加进去,处理 的 MST。
P4172 [WC2006] 水管局长
这道题就是维护 MST 的模板。
由于最小生成树删边不好做,所以我们加边倒序做。
然后我们发现,维护 MST 可以插入一条边,然后会形成一个环,删掉环上的最长的边即可。
结合 Kruskal 可以证明,因为当前加边如果不用,那就一定在 Kruskal 过程中在这些边后加入,所以这条边不加进去了。
然后维护边权有两种思路,一是转化成点权,子节点储存边权,二是中间新建一个节点。
维护子树信息
LCT 模板是维护链上信息的,但是它也可以维护子树信息。想想 Splay,我们 pushup 的时候可以把整个子树的信息 push 上去。
很多时候,我们需要单独开一个数组去记录虚儿子的信息。
P4219 [BJOI2014] 大融合
这道题中我们需要维护子树大小。
然而,LCT 只是维护实链信息的,所以我们需单独开一个数组记录虚儿子的信息。
这个用 记录,然后我们发现我们需要在 access 时,也就是改变虚实节点的时候更新。
pushup 时也不要忘了。
思路
每次询问,我们可以先断掉这条边,然后询问这两条边上的子树大小。
代码的主要修改点就是 access 还有 pushup 的逻辑。
void pushup(int x){
sum[x]=sum[ls]+sum[rs]+si[x]+1;
}
void access(int x){
for(int s=0;x;s=x,x=fa[x]){
splay(x);
si[x]+=sum[rs];
rs=s;
si[x]-=sum[rs];
pushup(x);
}
}
主函数中:
split(x,y);
ch[y][0]=fa[x]=0;
pushup(y);
makeroot(x);
makeroot(y);
long long ans=(long long)sum[x]*(long long)sum[y];
cout<<ans<<endl;
fa[x]=y;
si[y]+=sum[x];
pushup(y);
维护颜色数
很巧妙,每一个颜色用一个 splay。
这里就不详细讲了。
P5526 [Ynoi2012] 惊惶的 SCOI2016
P5526 [Ynoi2012] 惊惶的 SCOI2016。
CF1172E Nauuo and ODT。
给你一棵 个节点的树,每个点有个颜色,有 次修改,每次修改需要输出树上所有有向简单路径的颜色数的和。
首先,我们需要求对于每个颜色有多少条路径包含了。
神奇正难则反:求不包含这个颜色的路径数。然后此时的答案就是选取不包含这个颜色的节点,所有连通块大小的平方和。
然后就想办法用 LCT 维护颜色数。
思路
最简单的想法是对于每一个颜色维护 LCT,但是显然不行。
我们发现对于一种颜色,其余颜色怎么修改也影响不到,所以这是相对独立的。
又因为这道题没有强制在线,是每次询问后输出,我们又想到了类似差分的转为离线方法。
我们只需要离线下来处理每一个颜色即可。然后这就变成了一个双色问题,题解中说了一道 Qtree6,就是双色问题的基础。
至于维护什么?我们需要维护子树信息,我们维护一个点所有虚儿子的子树大小的平方和就行了。
维护 表示如果把 看作一个分割点,将它下方的所有虚边全部切断,那么得到的各个连通块(由实链连接的整体算一个块)的大小平方之和。然后连通块最上面的点是白点(也就是不能算进连通块的点)。
P7735 [NOI2021] 轻重边
直接用 LCT 的实/虚边模拟即可。不想写了,因为这道题写树剖更快。
树剖的话用一个技巧:染色。因为链上所有的节点都需要先变成轻边,所以只需要把这一段染成跟所有节点都不同的颜色即可,重边即颜色相同的一段。
配合线段树分治
这个...就有点恶心了吧,反正我还没学会。