P4565 [CTSC2018] 暴力写挂 题解
题意简析
给出两棵树,每棵树有 \(n\) 个节点,求点对 \((x, y)\),使得下式最大化:
\(n \le 366666\),边权可能为负。
思路解析
点分治/边分治 做法

以点分治为例,在有根的情况下分治结构如上。设 \(root\) 为根节点,\(x\) 是当前的重心。
显然的,非 \(root\) 所在的其余子树 \(son_1,son_2,son_{\cdots}\) ,地位相等,正常合并。
对于 \(root\) 所在的部分,还需要分类讨论成 \(fa_1, fa_2,fa_{\cdots},root\) 这几种情况。
对于每个部分分别暴力统计,显然是会超时的。依据经验,做有根点分治/边分治题目时,要利用题目中的特殊性质。
- 利用 LCA 与另一个点无关的性质,将影响范围缩小到系数。
- 利用题目的特殊性质,将 \(root\) 所在的部分进行动态单点查询。
- 有根的关键点不在 LCA(与本题无关)
为简化思考过程,以使用边分治为例。
对于跨越了中心边的点对 \((x, y)\),假设 \(y\) 处于根所在的连通块,且处在局部根为 \(r\) 的部分。则题中所要求的量转化为:
其中 \(x'\) 与 \(y\) 无关,于是可以把这部分贡献直接计算到 \(y\) 上。
现在所求的量为带点权的第二棵树上的 LCA 深度的最小值。仍然建立虚树进行树形 DP。时间复杂度 \(\mathcal{O}(n \log^2 n)\) 或 \(\mathcal{O}(n \log n)\)。
但是如果我们不会写虚树呢?
树上启发式合并(dsu on tree)做法
我们可以有两种写法:
- 完全启发性合并,优点是十分短小精悍。(
其实是我点分治调了两年半) - 先树链剖分选出重儿子,再暴力枚举轻儿子进行合并,优点是不会拆除父亲所在的部分。
对第一棵树进行重链剖分,利用 DSU on Tree 处理每个节点。对每个节点 \(x\),考虑以 \(x\) 为 LCA 的点对 \((u, v)\),其中 \(u\) 和 \(v\) 属于 \(x\) 的不同子树。
在第二棵树上进行树链剖分,对每条重链维护树状数组以支持动态更新和查询。对于每个点 \(v\),维护 \(a[v] = \text{depth}_T(v)\)(第一棵树中的深度)。动态添加/删除点时,更新重链和轻儿子子树的信息。
代码实现
点分治十分通用,边分治思路简单,对它们做树形 DP,可以在 \(\mathcal{O}(n \log^2 n)\) 和 \(\mathcal{O}(n \log n)\) 时间内解决。
DSU on Tree 的思路更加清新,时间复杂度 \(\mathcal{O}(n \log^3 n)\)。但是,我们可以考虑使用数据结构优化,使得时间复杂度降低到 \(\mathcal{O}(n \log^2 n)\),但常数大。或者也可以用小常数的树状数组进行优化,详见这篇题解。
由于 \(n \le 366666\),记得使用较快的输入方式。
后记
暴力写挂的这个标题很具有喜感啊。

浙公网安备 33010602011771号