[[TOC]]
前置知识:线性规划
斜率优化的思想其实和高中数学的线性规划有相似之处,因此建议没学过的同学先了解一下线性规划
这个视频讲解了高中的线性规划的相关知识
https://www.bilibili.com/video/BV1qg4y1v7Xy?p=4
一元一次函数:y=k⋅x+b,它的函数图像如下所示

其中k,b为定值,k为直线的斜率
由图可知如下的事实:
- 这条直线l上的所有点(xl,yl)都符合:yl−k⋅xl==d或者反过来说:在坐标
轴上所有符合y−k⋅x=d的点会组成一条直线,这条直线就是l
- B为直线l与y轴的交点,同时也是直线l上的点,所以yB−k⋅xB=d,此时xB==0,
所以得到:
yB=d
我们把这个距离称为截距.也就是说:直线l上的所有点yl−k⋅xl的值就是这个截距.
截距的性质
直线上的任意一个点的(y,x)的差值y−x的值就是截距
斜率优化
问题: 如下图所示,有多个点ai分布在坐标轴上,有一条直线y=k⋅x+b,其中k>0且为定值,b可以变化(这意味着,直线可以上下平移),那么如何选择一点ai,使直线经过该点时,使b值,也就是截距最小?

当我们选取一了一条直线,那么这条直线的斜率k就是固定的,此时只能上下平移的去移动这条直线,那么这个直线的截距b就是变化的.根据的思想:++排除不可能的点++.我们不禁会想哪些点是不可能的点?

从候选的点集中任意取三个点a,b,c,如下图所示.
设K(i,j)为点i,j之间的斜率,即K(i,j)=ΔxΔy=xj−xiyj−yi.
且这三个点满足发下的条件:
- xa<xb<xc
- K(a,b)=k1>k2=K(b,c)
::: oneline


:::
定理1: k3=K(a,c),k2<k3<k1
先证明k3<k1.延长直线a,b到达与y=xc的交点e.k1=K(a,b)=K(b,e)=xe−xbye−yb.又因为k1>k2,所以xe−xbye−yb>xc−xbyc−yb=k2.由定义可知:xe=xc,所以ye−yb>yc−yb⇒ye>yc.由上得到:
k3=xc−xayc−ya<xc−xaye−ya=k1(a)再证明k2<k3.延长直线c,b到达与y=xa的交点f.k2=K(b,c)=K(f,b)=xb−xfyb−yf.又因为k1>k2,所以xb−xayb−ya>xb−xfyb−yf=k2.由定义可知:xf=xa,所以yb−ya>yb−yf⇒ya<yf.由上得到:
k3=xc−xayc−ya>xc−xfyc−yf=k1(b)综合(a),(b)得到:k2<k3<k1.
推论1: 截距大小与斜率之间的关系

如图所示: k1表示直线a,b的斜率,直线l2的斜率kl2<k1,直线l1的斜率kl1>k1. 证明:
设B(l,k,a)表示有一个斜率为k直线l且结过点a的截距,B(l,k,a)=ya−k⋅xa.
1.当直线l的斜率k1>kl时,直线l经过点的截距B(l,kl,a)<B(l,kl,b).
证明: 因为k1>kl⇒xb−xayb−ya>kl⇒yb−ya>kl⋅(xb−xa),
B(l,kl,b)−B(l,kl,a)=yb−kl⋅xb−(ya−kl⋅xa)=(yb−ya)−kl⋅(xb−xa)>02.当直线l的斜率k1<kl时,直线l经过点的截距B(l,kl,a)>B(l,kl,b).证明方法同上.
综上: 当有两个点a,b 且 xa<xb∧K(a,b)>0时,直线l的k值如果小于K(a,b),那么经过a的截距小于经过b的截距.如果直线l的k的值如果大于K(a,b),那么经过b的截距小于经过a的截距.
定理2: b不可能成为答案.
设
- k表示直线line1的斜率
- ba=ya−k⋅xa,bb=yb−k⋅xb,bc=yc−k⋅xc
- ba,bb,bc分别表示直线line1经过点a,b,c时的截距.
那么现在只需要证明:ba⩽bb∨bc⩽bb的恒成立.
根据推论1,分情况讨论:
- k<k2<k1,此时ba<bb.
- k2<k<k1,此时bc<bb.
- k3<k1<k,此时bc<bb.
所以无论k的值是哪种情况,b都不可能成为答案.
推论2: 可能为答案的点集形成下凸壳
在后选点集(例如figure_2)里排除不可能点后形成一个k单调增加的序列,也就是下凸壳.

反证法: 假设k不是单调增加的,那么存在一对相邻的ki>ki+1,根据定理2,中间点ai+1不可能成为答案,与前提排除所有不可能点矛盾.
推论3: 第一个ki>k的起点就是最小截距
当直线l的斜率为k的时,经过下凸壳的哪个点时截距最小?
所有ki<k总是终点较优,所有ki>k总是起点较优.又因为下凸壳上的ki在递增. 所以直线l经过第一个ki>k的起点时得到最小截距.如果不存 在ki>k,那么最后一个点就是最小截距.
入门: 玩具装箱
题目地址:
解析
根据题目的意思可以很轻松的写出状态转移方程
dp[i]=j<imin{dp[j]+(sum[i]+i−sum[j]−j−L−1)2}(1)其中,sum[i]=1∑iCk,也就是前缀和.显然如果直接按这个方程来做,复杂度为O(n2)
使用 斜率优化
发现公式(1)是一个关于两个变量i,j二元公式.其中变化的只有j,如果我们可以把是的变化拆分成两个部分(X(j),Y(j)),那么j∈[1,i−1]的每一次变化都会产生一对点,这些点都分布在平面上.
且我们想到得到的值是:min{k⋅X(j)+Y(j)},k为定值,那不就是求斜率为k的直线经过那对点可以得到小截距吗?那么问题就为上面斜率问题.
设
k(i)X(j)=sum[i]+i−L−1=sum[j]+j
则可以得到
dp[i]=min{dp[j]+(k(i)−X(j))2}=min{dp[j]+k(i)2−2⋅k(i)⋅X(j)+X(j)2}=min{−2⋅k(i)⋅X(j)+dp[j]+X(j)2+k(i)2}
再设
Y(j)=dp[j]+X(j)2
因为k(i)是定值,所以可以把k(i)2移出来,则得到
dp[i]=min{−2⋅k(i)⋅X(j)+Y(j)}+k(i)2
我们注意到\fcolorbox{red}{aqua}{$- 2\cdot k(i) \cdot X(j) + Y(j) $}形如z = kx+y,
我们设直线l(j)表示为:
l(j)=−2k(i)⋅X(j)+Y(j)
于是就得到
dp[i]=min{l(j)}+k(i)2
显然我们要求的是\min\{l(j)\}, 1 \leqslant j < i,这个公式表示的意思就是: 我们要求直线方程线性规划l(j)的最小值
定义域为j∈[1,i)之间形成的点集P:{(X(1),Y(1)),(X(2),Y(2)),⋯}
对于点集P中的每一个点p,都会有一条斜率为k(i)的直线经过p,直线上的点
代入公式k⋅x+y的值一样
,而它们的值就是截距
所以我们只需要找到最小的截距
同时,基于上面的公式,我们可以知道以下事实:
- k(i)值为正值,且随着i单调增加
证明 需要维护一个凸包
凸包上的哪个点是答案
凸包上的如何添加点
所以
我们需要维护一个下凸壳
且壳上的点斜率递增
- 在壳上找到最优点
- 在壳上添加新的点
更一般的公式推断
我们有一个这样的状态转移方程
dp[i]=j∈[l,r]min{d(j)+B(i)+X(j)⋅k(i)}
- X(j)⋅k(i) 表示既与i有关又与j有关的项,因为i是固定的,通常X(i)的值也是定值
- d(j) 表示只与j有关的项
- B(i) 表示只与i有关的项,因为i是固定的,通常这个项的值也是定值
这样就可以看成这样的一条直线的公式
lj⇒y=k(i)⋅x+d(j)
那可以把原式子写成
\begin{equation}
dp[i]=\min\limits_{j\in[l,r]}{\colorbox{aqua}{ lj(k(i)) } }+d(i)
\end{equation}
所以对于每一个状态i,可以得到对应的k(i),那么根据lj就得到了对的值
也就是lj这条直线的线性规划
对于本题来说
\begin{equation}
dp[i]=\min\limits_{j\in[l,r]}{\colorbox{aqua}{ lj(k(i)) } }+d(i)
\end{equation}
X(j) 是
K(i) 是
为什么我们需要维护一个下凸壳
? 那么第一个满足条件的P值 如何求解最值,找到第一个斜率大于k(i)的点
为什么要维护一个单调队列
单调队列如何添加点
如何得到头(update)
TODO
dp[0]应该是什么值?
方法2 : 推理法
TODO
我需要使用asymoto
画图
所以需要 asymoto的笔记
代码1: 朴素
代码2: 模块
参考