Loading

题解 Tree

考虑一个不带修改的版本。我们在树上做最大权匹配,使用经典的树形 DP。设
\(dp_0(u)\) 表示 \(u\) 不与父亲匹配时,\(u\) 子树内的最大权匹配;
\(dp_1(u)\) 表示 \(u\) 与父亲匹配时,\(u\) 子树内的最大权匹配。

考虑 \(u\) 的所有子节点 \(v\)。如果 \(u\) 不与父亲匹配,显然它至多只能与一个子节点匹配,因此推出来

\[dp_0(u)=\sum dp_0(v)+\max\Bigl(0,\max_v\bigl(dp_1(v)-dp_0(v)\bigr)\Bigr). \]

如果 \(u\) 与父亲匹配,那么它不能再和任何子节点匹配,得出

\[dp_1(u)=\sum dp_0(v)+w(u,\text{parent}). \]

显而易见子树向父亲传递的信息,本质上只有两个值:\(dp_0\)\(dp_1\),而父亲真正关心的是差值 \(dp_1-dp_0\)。在没有修改的情况下,直接 DFS 一次即可完成,时间复杂度是 \(O(n)\)

不难发现一次修改会影响对应子节点到根的一整条路径。如果每次修改都沿着路径重新做 DP,单次最坏是 \(O(n)\),总复杂度达到 \(O(nq)\)


考虑如何更优。

不妨换一个角度来看这个转移。注意到一个节点对父亲的影响,其实是一个 父亲是否被选 到 子树最优值 的映射关系。我们可以把父亲的状态记为 \([f_0,f_1]\),那么节点 \(u\) 的转移可以完整地表示为一个 \(2\times2\) 的 max-plus 矩阵。
显然在其中,所有轻儿子的贡献可以提前合并,只保留 \(\sum dp_0\)\(\max(dp_1-dp_0)\) 两个量,与父亲相连的那条边,显然只会影响 \(u\) 被选中的那一项。

这样,一条重链上的 DP 合并就等价于这些矩阵的连续乘积。我们在线段树上维护每个节点对应的矩阵,区间查询时做矩阵合并即可。

当一条边权发生修改时,只会影响对应子节点的矩阵。我们先在线段树上更新该点,然后向上更新重链;如果链头的 DP 发生变化,再继续向父节点传播。注意到每向上一次必然跨过一条轻边,而一条根到叶路径上的轻边数量是 \(O(\log n)\),可以证明一次修改最多触发 \(O(\log n)\) 次链更新。

显然根节点不能与父亲匹配,所以答案始终是根节点的 \(dp_0\)
时间复杂度 \(O(n+q\log^2 n)\)。那么对于本题就是十分有优势的了。

posted @ 2026-02-01 22:33  MagnusSM2  阅读(23)  评论(0)    收藏  举报