DDP 学习笔记

Part 1

我们定义广义矩阵乘法:

\[C_{i,j} = \oplus_{k=1}^{n} A_{i,k} \otimes B_{k,j} \]

声称矩阵乘法满足结合律,仅需满足 \(\otimes\) 有结合律,且 \(\otimes\)\(\oplus\) 有分配律。
常见的卷积有 \(\min +\)\(\max +\) 卷积;以及图论的邻接矩阵 \(or \ and\) 卷积,表示在 \(k\) 次的意义下,表示点 \(u\) 经过 \(k\) 步是否能到达 \(v\)

由于矩阵计算的性质,可以通过矩阵乘法刻画 DP 的状态转移。不一定是线性,只需满足广义矩阵乘法的性质即可。

Part 2

以树上最大独立集为例。

若直接跑复杂度爆炸。注意到 \(i\) 到根节点的链上至多出现 \(O(\log)\) 条重链。将轻重儿子分开考虑。

\(f_{i,0/1}\) 表示 \(i\) 是/否选取时,\(i\) 的子树内的最大价值;\(g_{i,0/1}\) 表示 \(i\) 的子树中,\(i\)重儿子不选的前提下,\(i\) 的子树内的最大价值。令 \(s_i\)\(i\) 的重儿子。

\[\begin{aligned} g_{i,0} &= \sum_{u \in \mathrm{son}(i) \wedge u \neq s_i} \max(f_{u,0}, f_{u,1}) \\ g_{i,1} &= v_i + \sum_{u \in \mathrm{son}(i) \wedge u \neq s_i} f_{u,0} \\ f_{i,0} &= g_{i,0} + \max(f_{s_i,0}, f_{s_i,1}) \\ f_{i,1} &= g_{i,1} + f_{s_i,0} \end{aligned} \]

于是可以得出

\[[f_{s_i,0} \quad f_{s_i,1}] \times \begin{bmatrix} g_{i,0} & g_{i,1} \\ g_{i,0} & -\infty \end{bmatrix} \rightarrow [f_{i,0} \quad f_{i,1}] \]

其形式为 \(\max, +\) 卷积,满足分配律

\(f_{i,0/1}\) 的形式为 \(F(i)\)\(g_{i,0/1}\) 的形式为 \(G(i)\)

\[\begin{aligned} F(s_i), G(i) \rightarrow F(i)\\ F(son_i\setminus s_i) \rightarrow G(i) \end{aligned} \]

由第一个式子,发现 \(F(i)\) 仅仅和 \(i\) 所在的重链有关,设重链的头为 \(top_i\),重链的尾为 \(end_i\)。发现 \(F(i)\) 就为 \((\prod_{j=i}^{fa_{end_i}} G(j)) \times F(end_i)\)(这里的 \(\prod\) 指在树上的链)。由于重链的性质,\(end_i\) 为叶子结点,则 \(F(end_i) = G(end_i)\)。于是可以得出,\(F(i)\)\(i\)\(end_i\) 所有 \(G\) 的乘积。所以现在 \(F(i)\) 是可以用 \(G\) 取代的,而 \(F\) 本质上也成为了 \(G\) 的中间值,没有实质性作用。只需快速得出 \(G(i)\) 即可。

Part 3

接下来是所有 DDP 都要思考的关键问题。

我们发现 \(G\) 的修改仅存在于轻边连接的深度较小的节点,记这个点为 \(i\);修改的轻儿子记为 \(j\)。要想修改 \(G(i)\),就必须知道它的轻儿子的 \(F\)。由于 \(G\) 的求法是对 \(F\) 具有可减性的,所以可以先求出 \(F(j)\) 原值,在 \(G(i)\) 中减去,再加上 \(F(j)\) 的新值。考察修改 \(i\),发现其实是 \(G(i)\) 中的 \(val_i\) 发生了改变;于是在求原值后,加上新值前更新即可。

至此,已经完成了 DDP 的核心内容。具体的,要实现以下的操作:

  • 线段树支持单点修改,维护区间乘积(矩阵)。
  • 重链剖分。

实现不难。复杂度为 \(O(n \log^2 n \times w)\),其中 \(w\) 为矩阵运算的常数。

posted @ 2026-07-03 09:57  LoserBpds  阅读(4)  评论(0)    收藏  举报