斜率优化 DP 核心推导与笔记
斜率优化 DP 核心推导与笔记
一、适用形式
DP 转移方程可写成:
\[dp[i] = \min_{j < i} \{ f(j) \cdot g(i) + dp[j] \} + h(i)
\]
或最大值形式:
\[dp[i] = \max_{j < i} \{ f(j) \cdot g(i) + dp[j] \} + sum
\]
核心特征:\(f(j)\) 只与 \(j\) 有关,\(g(i)\) 只与 \(i\) 有关,两者以乘积形式出现。
二、点视角的转化
2.1 设点坐标
令:
\[x_j = f(j),y_j = dp[j]
\]
原式中需要最小化的部分为:
\[f(j) \cdot g(i) + dp[j] = g(i) \cdot x_j + y_j
\]
记 \(E = g(i) \cdot x_j + y_j\),我们要求 \(\min E\)。
2.2 转化为几何问题
考虑一条斜率为 \(-g(i)\) 的直线:
\[y = -g(i) \cdot x + E
\]
当它过点 \((x_j, y_j)\) 时,截距为:
\[E = y_j + g(i) \cdot x_j
\]
这正是我们要最小化的值。
所以,我们本质上就是要最小化 \(E\) 的值。
几何操作:用一条斜率为 \(-g(i)\) 的直线,从 y 轴负无穷远处(\(E\) 极小的方向)向上平移,它碰到的第一个点,就是使截距 \(E\) 最小的点。

如图,我们感性理解发现我们维护一个下凸壳(蓝色部分),所有不在下凸壳上的点一定会被包住,当直线从下放向上平移时,一定会优先碰到下凸壳上的点,所以所有不在下凸壳上的点就全部可以丢掉了。
因此总结:所有可能的最优解,都在点集的下凸壳上。
所以我们可以发现
求 \(\min\) → 斜率为 \(-g(i)\) 的直线从下往上碰 → 维护下凸壳
求 \(\max\) → 斜率为 \(-g(i)\) 的直线从上往下碰 → 维护上凸壳
然后我们可以发现几个性质:
- 加点的过程只依赖已算出的 \((x_j, y_j)\),只看点之间的几何位置关系,完全不关心 \(g(i)\) 是什么。
- 凸壳一旦维护好,对于后续任意查询斜率 \(-g(i)\),最优解一定在凸壳上,且可以高效定位。
- 凸壳就像一个建好的索引,查询什么值都保证返回正确结果。
因此可以用二分查找在凸壳上定位最优点。
若查询斜率也单调,可用单调队列在 \(O(1)\) 时间内维护队首。
三种情况的复杂度
| 条件 | 方法 | 复杂度 |
|---|---|---|
| \(f(j)\) 单调,\(g(i)\) 单调 | 单调队列 | \(O(n)\) |
| \(f(j)\) 单调,\(g(i)\) 不单调 | 单调栈 + 二分 | \(O(n \log n)\) |
| \(f(j)\) 不单调,\(g(i)\) 不单调 | 李超线段树 / CDQ 分治 | \(O(n \log n)\) |
可以自由转载

浙公网安备 33010602011771号