popossible の DP 选讲
popossible の DP 选讲
P4719 【模板】动态 DP
唯一听完基本能写出代码的题。
首先这个东西要是没有修改,那么就是那个没有上司的舞会。
$ f[i][0/1] $ : 第 $ i $ 个节点选/不选该节点的最大权值,然后从下到上 DP 即可。
然后发现改点权,会修改的 $ f $ 数组的值就是这个点到根节点上面的链的那一串 $ f $。
由于树有可能是链,所以要拿个什么玩意来平衡一下。
考虑树链剖分,$ f $ 数组的定义不变,再定义一个新的数组 $ g $,表示第 $ i $ 个节点选/不选该节点的最大权值(不包括重儿子)。
然后想一下如何由 $ f[v][0/1] $ 推到 $ f[u][0/1] $。
可以列出如下方程式:
发现这个东西有结合律,然后拿矩阵快速维护这个东西。
写出矩阵转移式:
重载乘法运算符,丢到线段树上维护。
然后修改的时候,因为 $ g $ 数组没有维护重儿子,所以每一次只会修改树剖上面的轻边,也就是最多只会修改 $ log_2 n $ 次。
每一次修改 $ log n $ ,所以总时间复杂度 $ n log^2 n $ 。
感觉这个只修改链头的 trick 跟 P5314 比较像。
P3350 [ZJOI2016] 旅行者
分治题。
首先对于每一次询问 Dijkstra 一遍肯定是不行的。
考虑离线下来。
每一次将这一小矩形按长边对半分割,得到两种询问。
第一种就是询问的两个点都在分割线的同一侧,第二种就是询问的两个点跨越的分割线。
对于第一种询问我们继续分割小矩形,然后处理第二种询问。
我们暴力枚举分割线上的每一个点,求出它们到这个矩形内每一个点的最短路径。
然后枚举被划在这个矩形内的每组询问,更新答案即可。
正确性显然,复杂度不会证。
P6192 【模板】最小斯坦纳树
状压 DP。
题目给你 $ k $ 个关键点,然后让你用最小的边权将它们联通,求这个最小边权。
首先设 $ f[i][S] $ : 子集为 S,并且一定包含点 i 的边权和最小值。
这个有两种转移。
第一种就是两个连通块之间的转移。
即 $ f[i][S] = min(f[i][S],f[i][T]+f[i][S \oplus T]) $ ($ \oplus $ 表示异或运算)。
第二种就是点与点之间的转移。
直接跑 Dijkstra 算法即可。
P1758 [NOI2009] 管道取珠
非常有趣的一个 trick 。
你发现这个贡献的平方非常奇怪,于是你考虑把它给拆开。
然后这个东西就相当于有两个人,第一个人的操作数目为 $ a_i $,第二个人的操作数目为 $ a_i $,将两个人的贡献乘起来。
然后就可以 DP 了。
令 $ f[k][i][j] $ 表示第一个人上面取了 $ i $ 个,第二个人上面取了 $ j $ 个的方案数。
列出转移方程式:
做完了。
P5024 [NOIP 2018 提高组] 保卫王国
动态DP多倍经验。
动态DP模板题要求的是最大权独立集,这题要求的是最小权覆盖集。
有个结论就是最小权覆盖集=全集-最大权独立集。
然后就是一样的了。
必须选和不能选可以转化为改点权。
必须选就改成负无穷大,不能选就改成无穷大,统计答案的时候就把加了的减掉就好了。
P4294 [WC2008] 游览计划
最小斯坦纳树多倍经验。
给你 $ k $ 个点,让你求把这 $ k $ 个点之间联通的最短路,然后输出方案。
输出方案不太好搞。
在每一次 Dijkstra 转移和枚举连通块的时候记录前驱,然后 DFS 一遍搞定。
还要注意点权化边权的一点细节,总得来说不是很难写,还是有点细节的。
P9871 [NOIP2023] 天天爱打卡
线段树优化 DP。
慢慢一步一步推就不是很困难。
首先想一个最简单的暴力DP。
设 $ f[i] $ 表示考虑到第 $ i $ 天可达到的最高能量值。
列出转移式子:$ f[i] = f[j-2] + w(j,i) + (i-j+1) * d $ ,其中 $ i-k+1 \le j \le i $。
其中 $ w(i,j) $ 表示的是 $ [i,j] $ 之间一直跑步可以造成的贡献数。
这个 $ w(i,j) $ 暴力算是 $ O(n) $ 的。
如果一个任务可以造成贡献那么 $ j<=l $ 且 $ r<=i $ 。
我们用一个 $ vector $ 将每个询问的在右端点处存下来,然后转移的时候从小往大加入。
那么 $ r<=i $ 这个条件是一定满足的,只需要考虑 $ j<=l $ 即可。
这个东西拿树状数组就可以维护。
然后这个 DP 就是 $ O(n k \log n) $ 的了。
你又发现其实不需要记录 $ n $ 种状态,因为真正有用的状态只有 $ m $ 个任务的两个端点。
离散化一下即可做到 $ O(m k \log m) $ 。
你又发现每一次转移过来的是一个区间的最大值。
然后每一次转移完的答案都会对后面的一个区间产生影响。
区间加区间最大值?
线段树即可。

浙公网安备 33010602011771号