1. 写出 dp\text{dp} 方程后,要先判断能不能使用斜优,即是否存在 function(i)function(j)function(i)*function(j)
    的项或者 Y(j)Y(j)X(j)X(j)\frac{Y(j)-Y(j')}{X(j)-X(j')} 的形式。

  2. 通过大小于符号或者 bbdp[i]dp[i] 的符号结合题目要求 (min/max)(\min/ \max)
    判断是上凸包还是下凸包,不要见一个方程就直接盲猜一个下凸。

  3. X(j)X(j) 非严格递增时,在求斜率时可能会出现 X(j1)=X(j2)X(j_1)=X(j_2)的情况,此时最好是写成这样的形式:return Y(j)>=Y(i)?inf:-inf,而不要直接返回 infinf 或者inf-inf,在某些题中情况较复杂,如果不小心画错了图,返回了一个错误的极值就完了,而且这种错误只用简单数据还很难查出来。

  4. 注意比较 k0[i]k_0[i]slope(j1,j2)slope(j_1,j_2) 要写规范,要用右边的点减去左边的点进行计算(结合 (3)(3)来看,可防止返回错误的极值),如果用的代数法理解,写出了 (X(j2)-X(j1))*k0<=Y(j2)-Y(j1)(X(j2)-X(j1))*k0<=Y(j2)-Y(j1),而恰巧 j1,j2j_1,j_2又写反了,便会出现等式两边同除了负数却没变号的情况。当然用 k0k_0Y(j2)Y(j1)X(j2)X(j1)\frac {Y(j_2)-Y(j_1)}{X(j_2)-X(j_1)} 进行比较是没有这种问题的。

  5. 队列初始化大多都要塞入一个点 P(0)P(0),比如 玩具装箱 toy\text{toy},需要塞入P(S[0],dp[0]+(S[0]+L)2)P(S[0],dp[0]+(S[0]+L)^2)P(0,0)P(0,0),其代表的决策点为 j=0j=0

  6. 手写队列的初始化是 h=1,t=0,由于塞了初始点导致 tt11,所以在一些题解中可以看到 h=t=1 甚至是 h=t=0h=t=2 之类的写法,其实是因为省去了塞初始点的代码。它们都是等价的。

  7. 手写队列判断不为空的条件是 h<=t ,而出入队判断都需要有至少 22 两个元素才能进行操作。所以应是 h<t

  8. 计算斜率可能会因为向下取整而出现误差,所以 slopeslope 函数最好设为 longlong doubledouble 类型。

  9. 可能会有一部分的 dp\text{dp} 初始值无法转移过来,需要手动提前弄一下,例如 摆渡车
    [P5017]\text{[P5017]}

  10. 在比较两个斜率时,尽量写上等于,即 <= 和 >= 而不是 < 和 >。这样写对于去重有奇效(有重点时会导致斜率分母出锅),但不要以为这样就可以完全去重,因为要考虑的情况可能会非常复杂,所以还是推荐加上 3 中提到的特判,确保万无一失。


(题单)

1
2
3
4
5
6
7
8
9
10
11
玩具装箱 toy [HNOI2008] [P3195]
土地征用 Land Acquisition G [P2900]
征途 [SDOI2016] [P4072]
Cats Transport [CF311B]
摆渡车 [NOIP2018] [P5017]
仓库建设 [ZJOI2007] [P2120]
序列分割 [APIO2014] [P3648]
任务安排 2 [Loj10185] [Poj1180]
锯木厂选址 [CEOI2004] [P4360]
特别行动队 [APIO2010] [P3628]
国王饮水记 [NOI2016] [P1721]

(以此处为分界线,上面都是 X(j)X(j)k0[i]k_0[i] 均单调的例子)

1
2
3
4
5
6
7
任务安排 3 [SDOI2012] [P5785] [Loj10186]
[Bzoj2726]( X(j) 单调 k_0[i] 不单调)
高速公路 [P3994]( X(j) 单调 k_0[i] 不单调。树上转移)
购票 [NOI2014] [P2305]( X(j) 单调 k_0[i] 不单调。树上转移)
Building Bridges [CEOI2017] [P4655]( X(j) 与 k_0[i]
均不单调)
货币兑换 [NOI2007] [P4027]( X(j) 与 k_0[i] 均不单调)

(做题记录)


P4072(SDOI2016) 征途

给定 nn 个数 a1na_{1\ldots n} ,划分成 mm 段,令方差为 ss ,求 s×m2s \times m^2 的最小值

欢乐的推式子时间

设分成 x1mx_{1\ldots m}

m2s=m2(x1x)2+(x2x)2++(xnx)2m=m(i=1mxi2+mx22xi=1mxi)=mi=1nxi2+(i=1nxi)22(i=1nxi)2=mi=1nxi2(i=1nxi)2\begin{aligned} m^2s&=m^2\dfrac{(x_1-\overline x)^2+(x_2-\overline x)^2+\cdots+(x_n-\overline x)^2}{m}\\ &=m(\sum_{i=1}^m{x_i}^2+m\overline x^2-2\overline x\sum_{i=1}^mx_i)\\ &=m\sum_{i=1}^n{x_i}^2+(\sum_{i=1}^nx_i)^2-2(\sum_{i=1}^nx_i)^2\\ &=m\sum_{i=1}^n{x_i}^2-(\sum_{i=1}^nx_i)^2 \end{aligned}

发现 (i=1nxi)2(\sum_{i=1}^nx_i)^2 是定值,就是求 i=1nxi2\sum_{i=1}^n{x_i}^2 的最小值

经典的斜率优化问题

f(x,t)f(x,t) 表示将前 xx 个数划分成 tt 段,平方和的最小值。

sxs_x 表示 a1+a2++axa_1+a_2+\ldots+a_x 的值

f(x,t)=min1y<x(f(y,t1)+(sxsy)2)=min1y<x(f(y,t1)+sx2+sy22sxsy)=min1y<x(f(y,t1)+sy22sxsy)+sx2\begin{aligned} f(x,t)&=\min_{1\le y<x}(f(y,t-1)+(s_x-s_y)^2)\\ &=\min_{1\le y<x}(f(y,t-1)+{s_x}^2+{s_y}^2-2s_xs_y)\\ &=\min_{1\le y<x}(f(y,t-1)+{s_y}^2-2s_xs_y)+{s_x}^2 \end{aligned}

min 去掉,移个项,看的更清楚些

f(y,t1)+sy2=2sxsy+f(x,t)sx2f(y,t-1)+{s_y}^2=2s_xs_y+f(x,t)-{s_x}^2

Bx=f(x,t1)+sx2B_x=f(x,t-1)+{s_x}^2Ax=sxA_x=s_x

那么就是求一个经过 (Ay,By)(A_y,B_y) 的点,斜率为 2sx2s_xf(x,t)f(x,t) 就是截距加上 sx2{s_x}^2

找截距最小的直线,维护下凸包。

(Ay2,B<!swig2>)(A_{y_2},B) 比 更(Ay1,B<!swig3>)(A_{y_1},B)

则有 (By2By1)Ay2Ay1<2sx\dfrac{(B_{y_2}-B_{y_1})}{A_{y_2}-A_{y_1}}<2s_x

sxs_x 单增,单调队列维护。

注意:维护凸包的时候记得用 slope(q[tail - 1], q[tail]) 不是 slope(tail - 1, tail)!!!!

挂了两遍了


P2120 (ZJOI2007)仓库建设

NN 个工厂,由高到底分布在一座山上.工厂 11 在山顶,工厂 nn 在山脚.第 ii 个工厂有 pip_i 件产品,在第 ii 个工厂位置建立仓库的费用是 cic_i.对于没有建立仓库的工厂,要将产品运往山下的仓库(即只能运往编号更大的工厂的仓库)。一件产品运送 11 个单位距离的费用是 11

假设建立的仓库容量都都是足够大的,且已知:
工厂 ii 距离工厂 11 的距离 did_i(其中 d1=0d_1=0);
工厂 ii 目前已有成品数量 pip_i
在工厂 ii 建立仓库的费用 cic_i

求最小费用(建造费用+运输费用)

f(x)f(x) 表示在第 xx 个位置修仓库,将工厂 1x1\ldots x 的产品全部运到仓库(不一定是仓库 xx )的最小费用

易得转移方程

f(x)=min1y<x(f(y)+i=y+1xpi(dxdi)+cx)f(x)=\min_{1\le y<x}(f(y)+\sum_{i=y+1}^{x}p_i(d_x-d_i)+c_x)

化简得

f(x)=f(y)+dxi=y+1xpii=y+1xdipi+cxf(x)=f(y)+d_x\sum_{i=y+1}^{x}p_i-\sum_{i=y+1}^{x}d_ip_i+c_x

不妨设 ax=i=1xpia_x=\sum_{i=1}^{x}p_ibx=i=1xdipib_x=\sum_{i=1}^{x}d_ip_i

f(x)=f(y)+dx(axay)bx+by+cx=f(y)+dxaxdxaybx+by+cx\begin{aligned} f(x)&=f(y)+d_x(a_x-a_y)-b_x+b_y+c_x\\ &=f(y)+d_xa_x-d_xa_y-b_x+b_y+c_x \end{aligned}

f(y)+b(y)=dxay+f(x)dxaxcxYK  XB\begin{aligned} &\underbrace {f(y)+b(y)}=\underbrace{d_x}\underbrace{a_y}+\underbrace{f(x)-d_xa_x-c_x}\\ &\qquad Y\qquad\qquad K\quad\ \ X\qquad\qquad\quad B \end{aligned}

化成了 Y=KX+BY=KX+B 的形式,斜率优化,单调队列。

注意:在队列初始化的时候一定要放一个空元素,否则相当于强制在 11 点放了一个仓库!!!