斜率优化

· · 个人记录

斜率优化可以优化这样的柿子:

f(i) = \max\limits_j f(j) - a_i a_j + b_j

i 转移时,若 j < kk 优,那么

\begin{aligned} & f(j) - a_ia_j + b_j \gt f(k)-a_ia_k+b_k \\ & f(j) + b_j - f(k) - b_k \gt a_i(a_j - a_k) \\ & \dfrac{f(j) + b_j - f(k) - b_k}{a_j-a_k} \gt a_i \end{aligned}

我们将 (a_j, f(j) + b_j) 看作是一个点,那么就相当于这当直线 P_jP_k 的斜率大于 a_i 时,jk 优。

这也就是一个下凸壳。我们用单调队列就可以维护。

注意到如果 a_i 单增,我们所切的斜率就单增,那么转移就可以做到均摊 O(1)

如果要求的是最小值,那么当斜率小于 a_ij 更优,于是我们就维护一个下凸壳,斜率是单调递减的,于是我们就要保证切的时候斜率也单调递减。

例题 P3648 [APIO2014] 序列分割

转移是显然的

\begin{aligned} f(i, j) &= \max_{k=0}^{i-1} f(k, j - 1) +\sigma_{k} (\sigma_i - \sigma_k) \\ & = \max f(k, j - 1) - \sigma_k^2 + \sigma_k\sigma_i \end{aligned}

这个转移是 O(n) 的。我们考虑怎么优化。

首先滚动掉第二维然后考虑。

每次用 $\sigma_i$ 去切即可。