详细揭秘:子树补回滚莫队线性对数解法
首先是前置知识。这里的问题抽象一下以后就是:有 \(m\) 个满足双单调性质的区间分布在 \([1, n]\) 内,每个点上有两个单位信息 \(a_i, b_i\),且这种信息的特点是支持且仅支持每次合并上一个单位信息(回滚莫队问题的信息的经典形态);现在要求对于每个区间求区间内部点的 \(a\) 和外部点的 \(b\) 合并在一起得到的信息。结论是我们可以通过分治做到 \((n+m) \log n\)。
子树补回滚莫队是指什么呢?其实就是说一棵树上每个点挂一个回滚莫队单位信息,然后对于每个点求子树外部的所有信息合并结果。题如其名,直接跑 DFS 序上的回滚莫队就给出了单根号做法,比较平凡直接略过。接下来我们先描述一种根据闫陈效基本定理(乐)可知没有显著优势的 \(\mathrm O(n \log^2 n)\) 解法。
考虑树的某种 DFS 序。我们发现子树区间满足的性质是要么包含要么不交,而不是我们喜欢的双单调,所以我们必须对它做一些改造。首先我们有树上启发式合并这个工具,它可以轻松做子树回滚莫队,但是对于子树补无能为力。考虑在当前问题中它能起到什么作用:假设我们已经在一条重链的顶端求出了外部的信息,我们可以沿着重链向下递推传递——每次暴力加入轻子树内所有点即可。于是现在我们只需要求所有重链顶端的信息就行了。我们考虑一个粗暴的分组方法:按照一个点到达根路径上的轻边数量分组,容易发现组数是 \(\log n\);并且每一组内点都没有祖先后代关系,所以 DFS 序区间不交;而不交区间显然满足双单调,所以直接套用上述分治去做这个,我们就得到了双 \(\log\) 做法。十分的 naive。值得一提的是我以前非常死板地认为那个分治只能求区间内信息合并,所以把区间补用“序列复制一遍接在后面”转化成区间,把 zhk 大神当场吓晕过去,其实直接分治做区间内外都是可以的。
为了令这个解法拥有比较大的优势,我们考虑抛弃愚蠢的分组,对于每个重链把它旁边的轻儿子搞出来按顺序排好,那么某个特定轻儿子的信息就是重链上的信息并上重链外的信息再并上其它儿子的信息。考虑在这个重链上用类似线段树的分治解决这一问题。这样得到了和上面相同的双 \(\log\) 复杂度。回过头再看看这个过程,你会发现它在整个树上的分治结构看着非常像重链剖分套线段树,复杂度也是一样的两 \(\log\),然而我们知道重链剖分线段树可以优化到单 \(\log\):直接使用全局平衡二叉树即可。那么这题能不能用呢?答案是肯定的:在重链上分治的时候带上权重,加上一些精细实现即可。于是你上述问题做到了单 \(\log\),完全胜利!