Note - 斜率优化 DP

书接上回

这是一种用于优化 DP 的东西(废话),其可以优化的表达式形如 \(\operatorname{dp}_i = \max\{a_i+b_j+c_i d_j\}\)

通用的东西

我们推式子。

\(dp_i = \max\{a_i+b_j+c_i d_j\} = a_i+\max\{b_j+c_i d_j\}\)

我们拆掉 \(\max\) 继续推式子。

\(dp_i = a_i+b_j+c_i d_j \implies -b_j = c_i d_j + a_i - dp_i\)

然后我们把式子视为一次函数解析式,那么从几何意义上来说这就是一个过点 \((d_j, -b_j)\),斜率为 \(c_i\) 的一次函数,我们要最小化其纵截距,即 \(a_i - dp_i\)

在脑海中想象一个凸包后我们发现,答案会取到凸包切直线的那个点,即凸包上第一个斜率大于 \(c_i\) 的线段的起始点。

法 I(单调队列优化)

要求:\(c, d\) 递增。

因为 \(d\) 递增,点一定是从左往右加入的,我们可以维护一个单调队列求斜率,每次加入点时如果这个点和前面的点组成的线段破坏了凸包性质那么前面那个点就可以直接踢掉。

因为 \(c\) 递增,维护时把斜率小于 \(c_i\) 的直接踢掉。这是线性的。

法 II(队列+二分优化)

要求:\(d\) 递增。

我们不能直接把斜率小于 \(c_i\) 的直接踢掉了,只能二分斜率。

法 III(平衡树维护凸壳)

这下点不是从左往右加入的了……

我们可以使用平衡树维护凸壳,但是我懒得写平衡树,在这种情况下建议用法 IV。

法 IV(李超线段树)

我们观察到我们的第一个式子。

\(dp_i = a_i+\max\{b_j+c_i d_j\}\)

我们惊奇地发现 \(\max\) 内的部分是一个一次函数,于是问题就被转化为了给定一堆能动态加入一次函数求 \(x = c_i\) 时的最高点。

这不是李超树板子来着。

posted @ 2026-02-13 19:49  Hootime  阅读(6)  评论(0)    收藏  举报