2025.5.5 闲话:CF571D Campus 奇妙在线解法的一点想法
见此题解,细看解法妙不可言,虽然我觉得一点都不好想。
题解里关键句:
- 一看涉及到合并, 就想到了并查集
- 但有一些加啊, 赋值啊, 所以不可路径压缩, 那就按秩合并
一看就是并查集大佬。
题目中有很多把一个树根接到另一个树根上的操作,且没有断链操作,跟并查集的思想很像,所以大佬“一看就想到并查集”。
本人蒟蒻,不知道路径压缩能不能做加法、赋值等运算,但感觉应该很难,所以自然而然想到用另一种方法——路径压缩来优化复杂度。对于正确性:题目中每一个操作都是对树整体操作,所以父子关系改变不影响正确性(因为每次操作跟相对父子关系无关而只与那些点联通在一起有关)。
然后我们就可以愉快地用 \(\log\) 的按秩合并了。
接下来看具体操作。
如果只有第一类集合,那么每次在树(第一类树)上正常合并,加法直接往根上加。那么最后能够影响到 \(x\) 的就是它到树根的所有祖先节点,一路爬上去就可以 \(log\) 求解了。这是一个前缀和思想。
但是我们有第二类集合的整树(第二类树)推平操作,这时就要考虑这个操作对第一类查询有何影响。
首先,如果第一类树中 \(x\) 的祖先 \(p\) 被 \(p\) 在第二棵树中的祖先 \(q\) 置零,那么这仅仅是 \(p\) 被置零而作为 \(p\) 后代的 \(x\) 已经被 \(p\) 加过一次了,\(p\) 现在置零对它当前的值没有影响,换言之,我们不需要关注 \(x\) 的祖先被置零的情况。(这一点让我迷惑了很久)
其次,我们必须考虑 \(x\) 自身被置零的情况,这个很简单,从 \(x\) 在第二类树中一路往上找祖先即可(其祖先节点的置零都会影响 \(x\))对所有置零的事件取最大值即是 \(x\) 最后一次被置零的事件,从这以后 \(x\) 在第一类树中的加法操作才是有效的。
然后做法就出来了,找到最后置零时间后,在一类树中向上找到在该时间后的修改,加上即可。
题解中特别强调了:
如果 \(x\) 的父亲和 \(x\) 相连时刻比标记的时间大,则标记对 \(x\) 是无效的,这点对
add标记同理。
这是因为,如果发生了这种情况,那么这两个点相连的时间要晚于父节点操作的时间,这个父节点以前的操作也就影响不到 \(x\) 了,直接忽略掉即可。
本文采用 「CC-BY-NC 4.0」 创作共享协议,转载请注明作者及出处,禁止商业使用。
作者:Jerrycyx,原文链接:https://www.cnblogs.com/jerrycyx/p/18860335

浙公网安备 33010602011771号