2024-3月 DP 总结
换根 DP
- 换根 DP,又称二次扫描,一般用于求解无根树问题。大多数时候将 \(n\) 次 dfs 简化为 \(2\) 次从而优化算法。
经典套路:
\(1.\) 指定某个节点为根节点(一般为 \(1\))。
\(2.\) 第一次搜索完成预处理,同时得到该节点的解。
\(3.\) 第二次搜索进行换根 DP,由已知节点推出相邻节点。
具体地,设 \(f\) 和 \(g\) 两个数组分别表示第一次子树内的答案和以其为根的答案(也可以设子树外的答案)。第一次 dfs 处理 \(f\),第二次 dfs 通过父亲的 \(g\) 推出儿子。也即第一次自底向上,第二次自顶向下。这就是所谓“换根”的过程。
例题1 P3478 [POI2008] STA-Station
【题意】
给出一棵树,找出一个点来,使得以这个点为根时所有点的深度之和最大。
【解析】
设 \(f_i\) 表示 \(i\) 子树内的答案,则显然地,\(f_u=\sum_{v\in u}f_v+siz_v\),这里的 \(siz\) 表示子树大小。
第二次 dfs,考虑设 \(g_i\) 表示以 \(i\) 为整棵树的根的答案。则 \(g_v=g_u+n-2\times siz_v\)。特殊地,\(g_1=f_1\)。
答案为 \(\max g_i\),时空复杂度 \(O(n)\)。
例题2 CF1156D 0-1-Tree
可以左转我的题解。
斜率优化 DP
-
斜率优化,一般是在转移方程中当前为 \(i\),枚举决策点 \(j\),然后化简式子出现同时与 \(i\) 和 \(j\) 有关的项(如果没有可以单调队列)。这样的话有点像一次函数,形如 \(y=kx+b\),那么这里的 \(kx\) 就是与\(i\) 和 \(j\) 有关的项(具体题目具体分析)。问题变成查询最有决策点。
-
如果式子中的 \(x\) 与 \(y\) 都有单调性,可以使用单调队列线性维护。否则有两种做法:维护凸壳并二分或李超树(也可以平衡树或 cdq 分治,但我不会,就不弄巧成拙了)。这些做法是带一个 log 的。
经典套路:
\(1.\) 写出朴素转移方程。
\(2.\) 化简并设出 \(x,y,k,b\),根据所求决定维护上凸还是下凸(最大值还是最小值)。
\(3.\) 看单调性决定维护方式。
例题1 P3195 [HNOI2008] 玩具装箱
【题意】
给定一个序列,要求将其划分成若干段,一段划分为 \([i,j]\) 的费用为 \((j-i+\sum_{k=i}^jC_k-L)^2\)(这里的 \(C_k\) 为给定数组,\(L\) 为给定常量)。最小化划分序列的费用和。
【解析】
朴素的转移方程为:(设 \(f_i\) 表示考虑到 \(i\) 的答案,\(s_i\) 表示 \(C_i\) 的前缀和)
换元并化简,设 \(a_i=s_i+i,b_i=s_i+i+L+1\)。
先不管取 \(\min\),先推式子,并把只与 \(j\) 有关的移到一边,尝试分离 \(i\) 和 \(j\)。
我们发现,如果设 \(y=f_j+b_j^2,k=2\times a_i,x=b_j,b=f_i-a_i^2\),那么方程变成了一个一次函数形式 \(y=kx+b\)。所以要做的就是在二维平面中找一个斜率固定的直线使 \(b\) 最小。
观察数据,\(y=f_j+b_j^2\) 和 \(x=b_j\) 都单调递增,所以使用单调队列优化,时空复杂度线性。

浙公网安备 33010602011771号