整理:斜率优化

关于斜率优化的整理

我们先来看一道题。

HNOI2008 玩具装箱

题目描述

P 教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。

P 教授有编号为 \(1 \cdots n\)\(n\) 件玩具,第 \(i\) 件玩具经过压缩后的一维长度为 \(C_i\)

为了方便整理,P 教授要求:

  • 在一个一维容器中的玩具编号是连续的。

  • 同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物。形式地说,如果将第 \(i\) 件玩具到第 \(j\) 个玩具放到一个容器中,那么容器的长度将为 \(x=j-i+\sum\limits_{k=i}^{j}C_k\)

制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 \(x\),其制作费用为 \((x-L)^2\)。其中 \(L\) 是一个常量。P 教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过 \(L\)。但他希望所有容器的总费用最小。

数据范围与约定

对于全部的测试点,\(1 \leq n \leq 5 \times 10^4\)\(1 \leq L \leq 10^7\)\(1 \leq C_i \leq 10^7\)

这显然是一道 DP 题,状态容易得出,\(dp_i\) 表示装下前 \(i\) 个玩具的最小花费。

转移就是将若干个玩具作为一段装起来,\(dp_i=dp_j+(\sum_{k=j+1}^i c_k-L)^2\),显然利用前缀和优化求和过程,因此转移方程写为:

\(dp_i=dp_j+(pre_i-pre_j-L)^2\)

拆开式子:\(dp_i=dp_j+pre_i^2+pre_j^2+L^2-2pre_ipre_j-2pre_iL+2pre_jL\)

这看起来无法使用常规手段优化,因为式子比较复杂,有些项与 \(i,j\) 均相关,无法使用单调队列优化。

但是我们对式子进行简单变形:

\[dp_j+pre_j^2+2pre_jL=2pre_ipre_j+dp_i+2pre_iL-prei^2-L^2 \]

我们将 \(dp_j+pre_j^2+2pre_jL\) 设为 \(y\)\(2pre_i\) 设为 \(k\)\(pre_j\) 设为 \(x\)\(dp_i+2pre_iL-prei^2-L^2\) 设为 \(b\).

那么上面的式子就变成了 \(y=kx+b\),即一次函数。

现在问题就变成了平面上有若干个点 \((x,y)\),现在使用一条斜率为 \(k\) 的直线去分别经过这些点,求截距的最小值。

看上去还是无法解决。

但是这里我们有一个计算几何的工具:凸包[1]

所以我们对前面所有点维护下凸包,然后二分求切点即可。

而上面我们设出一次函数解析式,维护凸包,二分切点并最后进行转移的过程,就是所谓斜率优化。你问我为什么叫斜率优化?我也不知道。

斜率优化的基本过程

  1. 定义状态并写出转移方程。
  2. 化简式子并设出一次函数解析式。
  3. 套模版维护凸包。
  4. 二分求出切点,即转移位置。
  5. 转移。
  6. A 掉这道题

过程简单地如同如何将大象塞进冰箱。

实现细节

注意可以转移的区域,即可行决策点,当决策点不合法时要从凸包中删去。

二分时,定义 \(cal(i,j)\) 表示使用 \(j\) 这个决策点转移 \(i\),然后用 \(mid\)\(mid+1\) 比哪个更优即可。


  1. 凸包 - OI Wiki (oi-wiki.org) ↩︎

posted @ 2025-04-07 11:53  陈牧九  阅读(25)  评论(0)    收藏  举报