dp 的优化

单调队列优化

对于转移方程

fx=mink=pxx1{gk}+wx f_x=\min _{k=p_x}^{x-1}\{g_k\}+w_x

其中 pxp_x 单调不降。如果存在两个数 j,kj,kjkj \leq kgkgjg_k \leq g_j,那么决策 jj 是无用的。这意味着我们的最优决策表单调不降,所以可以用一个单调递增的队列进行优化。流程如下

  1. 队首元素不断出队,直到队首元素在给定范围中,此时队首元素就是状态 fxf_x 的最优决策。
  2. 计算 gxg_x,并插入单调队列的尾部,同时维护队列单调递增性。
  3. 重复上述步骤,可以发现每个状态只入队和出队一次,时间复杂度为 O(n)O(n)

斜率优化

直接讲比较迷,拿 HNOI2008 玩具装箱为栗子。

fif_i 是装好前 ii 个玩具的花费,枚举从那个玩具开始放。O(n2)O(n^2) 的转移方程如下

si=k=1icks_i = \sum_{k=1}^i c_k

fi=minj=0i1fj+(sisj+ij1L)2 f_i = \min_{j=0}^{i - 1} f_j+(s_i-s_j + i - j - 1 - L)^2

再令 si=k=1ick+is_i = \sum_{k=1}^i c_k+iL=L+1L = L+1

fi=minj=0i1fj+(sisjL)2化简得fi=si22si×L+fj+(sj+L)22sisj移同类项得fj+(sj+L)2=2sisj+fisi2+2si×L f_i = \min_{j=0}^{i - 1} f_j+(s_i-s_j -L)^2 \\ \text{化简得}\\ f_i=s_i^2-2s_i \times L+f_j+(s_j+L)^2-2s_is_j \\ \text{移同类项得}\\ f_j+(s_j+L)^2 =2s_is_j+ f_i - s_i^2 + 2s_i \times L\\

y=fj+(sj+L)2y = f_j+(s_j+L)^2k=2sik = 2s_ix=sjx =s_jb=fisi2+2si×Lb = f_i - s_i^2 + 2s_i \times L。那么得到了

y=kx+b y = kx + b

其中 xx 满足单调递增性,所以不用对柿子取反。同时,kk 和关于 jj 的解析式 yy 也单调递增,而 bb 中有要转移的 fi=b+si22si×Lf_i = b + s_i^2 - 2s_i \times L

可以发现斜率 kk 数已知的,并且 bfib - f_i 也是已知队。如果能求出一个点对 (x,y)(x,y),就可以求出 bb,进而求出 fif_i。要让 fif_i 最小就要让 bb 最小,如果把 (x,y)(x,y) 展现在坐标系上,我们用一条斜率为 kk 的直线从右下方向左上方移动,第一个在直线上的 (x,y)(x,y) 即为需要的点。

dp 的优化

考虑加一个点得到了直线 k2k_2,之前可选的点集中有一条直线 k1k_1。如果 k2>k1k_2 > k_1,那么加的点在以后可能用到,因为随着斜率的单调递增,选的点也逐渐靠上。如果 k1<k2k_1 < k_2,那么 k1k_1 能交的线,k2k_2 一定比它先交,所以 k1k_1 可以从点集中删除。

所以要维护的点集是一个下凸包。下凸包所有点的斜率是单调递增的,而且下凸包的下方没有其它的点。用单调队列维护,实现有亿点点细节。
dp 的优化

四边形不等式优化