斜率优化
斜率优化是一种用数据结构维护\(dp\)的某种单调性性质从而达到优化\(dp\)的效果。
抽象的说,斜率优化可通过维护一个下(上)凸壳优化形如\(f_i = min_{j=1}^{i-1}\{ f_j + g_{i,j}\}\)(\(max\)同理)的转移方程。
本文只有简单推导,更充分的理解需要数形结合,请移步\(OI\ Wiki\)或其他大佬的博客。
设\(f_i\)为在第\(i\)个位置建造最后一个仓库的最小代价。
不难得出朴素的\(O(n^2)\)转移方程
换成前缀和的形式,令\(P_i=\sum_{j=1}^{i}p_i\), \(S_i=\sum_{j=1}^ix_i\times p_i\)
若决策\(j\)优于决策\(k\),即
整理成斜率的形式
\(\because\)\(x_i\)单调递增,\(\therefore\)我们需要维护一个斜率单调递增的决策序列,即维护\(f_i\)函数的下凸壳。
使用单调队列维护即可,时间复杂度\(O(n)\)。
设\(t_i\)为何时出发的人刚好接走它,\(s_i=\sum_{j=1}^it_i\),\(f_{i,j}\)前\(i\)个人接走前\(j\)只猫的最小代价。
先忽略第一维考虑第二维转移,是和上面那题类似的模式。
使用同样的套路比较决策点,然后得到斜率的形式
同样使用单调队列维护,转移时多枚举一维即可,时间复杂度\(O(mp)\)
习题
例题 JSOI2011 柠檬
首先有结论:一段内首尾数字必定相同。
不难列出\(dp\)方程
其中\(s_i\)表示\(1-i\)中\(a_j=a_i\)的个数。
考虑决策点可得
看起来这个形式和上面两题相似,实则有些不同。
不难发现,上面两题转移越靠前越优,故用单调队列维护单调性。
此题转移越靠后越优,不难想到用单调栈维护单调性。
细节见代码,注意操作顺序。