-
写出 dp 方程后,要先判断能不能使用斜优,即是否存在 function(i)∗function(j)
的项或者 X(j)−X(j′)Y(j)−Y(j′) 的形式。
-
通过大小于符号或者 b 中 dp[i] 的符号结合题目要求 (min/max)
判断是上凸包还是下凸包,不要见一个方程就直接盲猜一个下凸。
-
当 X(j) 非严格递增时,在求斜率时可能会出现 X(j1)=X(j2)的情况,此时最好是写成这样的形式:return Y(j)>=Y(i)?inf:-inf
,而不要直接返回 inf 或者−inf,在某些题中情况较复杂,如果不小心画错了图,返回了一个错误的极值就完了,而且这种错误只用简单数据还很难查出来。
-
注意比较 k0[i] 和 slope(j1,j2) 要写规范,要用右边的点减去左边的点进行计算(结合 (3)来看,可防止返回错误的极值),如果用的代数法理解,写出了 (X(j2)-X(j1))*k0<=Y(j2)-Y(j1)
或(X(j2)-X(j1))*k0<=Y(j2)-Y(j1)
,而恰巧 j1,j2又写反了,便会出现等式两边同除了负数却没变号的情况。当然用 k0 和 X(j2)−X(j1)Y(j2)−Y(j1) 进行比较是没有这种问题的。
-
队列初始化大多都要塞入一个点 P(0),比如 玩具装箱 toy,需要塞入P(S[0],dp[0]+(S[0]+L)2) 即 P(0,0),其代表的决策点为 j=0。
-
手写队列的初始化是 h=1,t=0
,由于塞了初始点导致 t 加 1,所以在一些题解中可以看到 h=t=1
甚至是 h=t=0
,h=t=2
之类的写法,其实是因为省去了塞初始点的代码。它们都是等价的。
-
手写队列判断不为空的条件是 h<=t
,而出入队判断都需要有至少 2 两个元素才能进行操作。所以应是 h<t
。
-
计算斜率可能会因为向下取整而出现误差,所以 slope 函数最好设为 long double 类型。
-
可能会有一部分的 dp 初始值无法转移过来,需要手动提前弄一下,例如 摆渡车
[P5017]。
-
在比较两个斜率时,尽量写上等于,即 <= 和 >= 而不是 < 和 >。这样写对于去重有奇效(有重点时会导致斜率分母出锅),但不要以为这样就可以完全去重,因为要考虑的情况可能会非常复杂,所以还是推荐加上 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) 与 k0[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) 征途
给定 n 个数 a1…n ,划分成 m 段,令方差为 s ,求 s×m2 的最小值
欢乐的推式子时间
设分成 x1…m 。
m2s=m2m(x1−x)2+(x2−x)2+⋯+(xn−x)2=m(i=1∑mxi2+mx2−2xi=1∑mxi)=mi=1∑nxi2+(i=1∑nxi)2−2(i=1∑nxi)2=mi=1∑nxi2−(i=1∑nxi)2
发现 (∑i=1nxi)2 是定值,就是求 ∑i=1nxi2 的最小值
经典的斜率优化问题
设 f(x,t) 表示将前 x 个数划分成 t 段,平方和的最小值。
设 sx 表示 a1+a2+…+ax 的值
f(x,t)=1≤y<xmin(f(y,t−1)+(sx−sy)2)=1≤y<xmin(f(y,t−1)+sx2+sy2−2sxsy)=1≤y<xmin(f(y,t−1)+sy2−2sxsy)+sx2
min 去掉,移个项,看的更清楚些
f(y,t−1)+sy2=2sxsy+f(x,t)−sx2
令 Bx=f(x,t−1)+sx2 ,Ax=sx
那么就是求一个经过 (Ay,By) 的点,斜率为 2sx ,f(x,t) 就是截距加上 sx2 。
找截距最小的直线,维护下凸包。
若 (Ay2,B<!−−swig2−−>) 比 更(Ay1,B<!−−swig3−−>)优
则有 Ay2−Ay1(By2−By1)<2sx
sx 单增,单调队列维护。
注意:维护凸包的时候记得用 slope(q[tail - 1], q[tail])
不是 slope(tail - 1, tail)
!!!!
挂了两遍了
P2120 (ZJOI2007)仓库建设
有 N 个工厂,由高到底分布在一座山上.工厂 1 在山顶,工厂 n 在山脚.第 i 个工厂有 pi 件产品,在第 i 个工厂位置建立仓库的费用是 ci.对于没有建立仓库的工厂,要将产品运往山下的仓库(即只能运往编号更大的工厂的仓库)。一件产品运送 1 个单位距离的费用是 1 。
假设建立的仓库容量都都是足够大的,且已知:
工厂 i 距离工厂 1 的距离 di(其中 d1=0);
工厂 i 目前已有成品数量 pi ;
在工厂 i 建立仓库的费用 ci 。
求最小费用(建造费用+运输费用)
设 f(x) 表示在第 x 个位置修仓库,将工厂 1…x 的产品全部运到仓库(不一定是仓库 x )的最小费用
易得转移方程
f(x)=1≤y<xmin(f(y)+i=y+1∑xpi(dx−di)+cx)
化简得
f(x)=f(y)+dxi=y+1∑xpi−i=y+1∑xdipi+cx
不妨设 ax=∑i=1xpi,bx=∑i=1xdipi
则
f(x)=f(y)+dx(ax−ay)−bx+by+cx=f(y)+dxax−dxay−bx+by+cx
f(y)+b(y)=dxay+f(x)−dxax−cxYK XB
化成了 Y=KX+B 的形式,斜率优化,单调队列。
注意:在队列初始化的时候一定要放一个空元素,否则相当于强制在 1 点放了一个仓库!!!