动态DP

例题【洛谷P4719

给定一棵树,节点$x$的权值为$w[x]$,维护以下两个操作:

1. 修改一个节点的权值;

2. 询问当前的最大独立集的权值。

 

解:

假设没有修改操作,则是一个典型的树形动态规划。设$f[x][0]$表示未选择节点$x$的情况下的最大权值,$f[x][1]$表示选择了节点$x$的情况下的最大权值,则

$$ f[x][0] = \sum_{y \in \text{son}(x)} \max\{f[y][0], f[y][1]\}, $$

$$ f[x][1] = w[x] + \sum_{y \in \text{son}(x)} f[y][0]. $$

特别地,若$x$是叶子节点,则$f[x][0] = 0, f[x][1] = w[x]$.

 

将这棵树树链剖分后,令$\text{heavy}(x)$表示节点$x$的重儿子,$\text{light}(x)$表示节点$x$的轻儿子的集合。若$x$非叶节点,则

$$ f[x][0] = \max\{ f[\text{heavy}(x)][0], f[\text{heavy}(x)][1] \} + g[x][0], $$

$$ f[x][1] = f[\text{heavy}(x)][0] + g[x][1], $$

其中

$$ g[x][0] = \sum_{y \in \text{lignt}(x)} \max\{f[y][0], f[y][1]\}, $$

$$ g[x][1] = w[x]+ \sum_{y \in \text{lignt}(x)} f[y][0]. $$

 

我们引入广义矩阵乘法,其加法为$\max$,其乘法为$+$,对于两个矩阵$A$和$B$,其积$C = A*B$定义为

$$C_{ij} = \max_k \{A_{ik}+B_{kj}\}.$$

 

我们可以把节点$x$与其重儿子$\text{heavy}(x)$的动态规划递推式写作

$$ \begin{bmatrix} f[x][0] \\ f[x][1] \end{bmatrix} = \begin{bmatrix} g[x][0] & g[x][0] \\ g[x][1] & -\infty \end{bmatrix} * \begin{bmatrix} f[\text{heavy}(x)][0] \\ f[\text{heavy}(x)][1] \end{bmatrix}. $$

我们记

$$ M[x] = \begin{bmatrix} g[x][0] & g[x][0] \\ g[x][1] & -\infty \end{bmatrix}. $$

设$x = x_0 \to x_1 \to \dots \to x_k$是以$x$出发的重链,则以$x$为根的子树的最大独立集的权值可通过下式给出:

$$ \begin{bmatrix} f[x][0] \\ f[x][1] \end{bmatrix} = M[x_0] * M[x_1] * \dots * M[x_{k-1}] * \begin{bmatrix} 0 \\ w[x_k] \end{bmatrix}. $$

这个式子可以写得更优美一点:

$$ \begin{bmatrix} f[x][0] \\ f[x][1] \end{bmatrix} = M[x_0] * M[x_1] * \dots * M[x_k] * \begin{bmatrix} 0 \\ 0 \end{bmatrix}. $$

 

对于修改节点$x$的权值,我们只需要修改 $g[x][0], g[x][1]$ 以及节点$x$到根的路径中与其他重链交汇的那些节点,最多$O(\log n)$个。

故树链剖分能在$O(\log^2n)$的复杂度内维护单次操作。

 

P.S. 可以利用动态树(Link-Cut Tree)把复杂度进一步降为单次操作$O(\log n)$。甚至还可以维护其他操作,如修改一个节点的父节点,以及询问某个子树的最大独立集等。

 

然而这种神奇的动态DP居然在NOIP2018的Day2第三题【保卫王国】出现了。这也太超纲了吧,NOI2018的Day2第三题还差不多。

不一样的是,【保卫王国】求的是最小点集覆盖。但二分图中,最小点集覆盖 = 权值之和 - 最大独立集。因此两个问题的求解是等价的。

 

动态DP例题:

洛谷P4719

NOIP2018. 保卫王国

CEOI2019. Dynamic Diameter

posted @ 2019-07-23 21:40  liouzhou_101  阅读(309)  评论(0编辑  收藏  举报