斜率优化

斜率优化是一种用数据结构维护\(dp\)的某种单调性性质从而达到优化\(dp\)的效果。

抽象的说,斜率优化可通过维护一个下(上)凸壳优化形如\(f_i = min_{j=1}^{i-1}\{ f_j + g_{i,j}\}\)\(max\)同理)的转移方程。

本文只有简单推导,更充分的理解需要数形结合,请移步\(OI\ Wiki\)或其他大佬的博客。

例题 [ZJOI2007] 仓库建设

\(f_i\)为在第\(i\)个位置建造最后一个仓库的最小代价。

不难得出朴素的\(O(n^2)\)转移方程

\[f_i = min_{j = 0}^{i-1}\{f_j+x_i \times \sum_{k=j+1}^i p_k-\sum_{k=j+1}^ix_k\times p_k\}+c_i \]

换成前缀和的形式,令\(P_i=\sum_{j=1}^{i}p_i\), \(S_i=\sum_{j=1}^ix_i\times p_i\)

\[f_i=min_{j=0}^{i-1}\{ f_j+x_i\times(P_i-P_j)-S_i+S_j\}+c_i \]

若决策\(j\)优于决策\(k\),即

\[f_j+x_i\times(P_i-P_j)-S_i+S_j <f_k+x_i\times(P_i-P_k)-S_i+S_k \]

整理成斜率的形式

\[\frac{(f_j+S_j)-(f_k-S_k)}{S_j-S_k}<x_i \]

\(\because\)\(x_i\)单调递增,\(\therefore\)我们需要维护一个斜率单调递增的决策序列,即维护\(f_i\)函数的下凸壳

使用单调队列维护即可,时间复杂度\(O(n)\)

Code

例题 CF311B Cats Transport

\(t_i\)为何时出发的人刚好接走它,\(s_i=\sum_{j=1}^it_i\)\(f_{i,j}\)\(i\)个人接走前\(j\)只猫的最小代价。

\[f_{i,j}=min_{k=0}^{j-1}\{ f_{i-1,k}+t_j\times (j-k) -S_j+S_k\} \]

先忽略第一维考虑第二维转移,是和上面那题类似的模式。

使用同样的套路比较决策点,然后得到斜率的形式

\[\frac{(f_{j}+S_j)-(f_k+S_k)}{j-k}<t_i \]

同样使用单调队列维护,转移时多枚举一维即可,时间复杂度\(O(mp)\)

Code

习题

HNOI2008 玩具装箱 TOY

APIO2010 特别行动队

USACO08MAR Land Acquisition

例题 JSOI2011 柠檬

首先有结论:一段内首尾数字必定相同。

不难列出\(dp\)方程

\[f_i=max_{1 \leq j \leq i}^{a_i=a_j}\{f_{j-1}+a_i\times(s_i-s_j+1)^2\} \]

其中\(s_i\)表示\(1-i\)\(a_j=a_i\)的个数。

考虑决策点可得

\[\frac{(f_{j-1}+a_is_j^2)-(f_{k-1}+a_is_k^2)}{s_j-s_k}>2a_i(1+s_i) \]

看起来这个形式和上面两题相似,实则有些不同。

不难发现,上面两题转移越靠前越优,故用单调队列维护单调性。

此题转移越靠后越优,不难想到用单调栈维护单调性。

细节见代码,注意操作顺序。

Code

posted @ 2020-07-02 11:31  OIerC  阅读(94)  评论(0编辑  收藏  举报