斜率优化
斜率优化
大致思想:
将决策点视为若干二维平面上的点,将当前点的已知条件视为斜率,将 \(dp_i\) 视为截距。寻找经过某个点且斜率一定的直线的最小截距。(寻找最大截距时需要将 \(dp\) 取负,转化为最小,这样维护的凸包就始终是下凸包)
k,b,y的转换
转换的常见思路:若 \(i\) 为当前点,\(j\) 为最优决策点。把只与 \(j\) 有关的部分设为 \(Y(j)\);把 “由 \(i\),\(j\) 决定的部分中 \(y\) 的部分设为 \(X(j)\)”;把“由 \(i\),\(j\) 决定的部分中 \(i\) 的部分设为 \(K(i)\)”;把只与 \(i\) 有关的部分设为 \(b\).当然,有一些题目可能涉及到常数的计算,放入哪个部分都是可以的,为了方便,我常把它放入 \(b\)中.
实例:dp[i] = dp[j] - A * (s[i] - s[j]) * (s[i] - s[j]) - B * (s[i] - s[j]) - C;假设有这样一个递推式,那么会有如下的转换:
ll getx(int i) { return s[i]; }
ll gety(int i) { return dp[i] - A * s[i] * s[i] + B * s[i]; }
ll getk(int i) { return -2 * A * s[i]; }
DP过程
写出这道题的转移方程,将方程进行一些变形后把 \(k,b,y\) 求出。
对于每一个点 \(i\):
- 根据 \(K(i)\),求出点 \(i\) 的最优决策点 \(j\).(寻找切线的过程)
- 将 \(i\) 对应的点\((X(i),Y(i))\) 加入平面,并维护凸包。
求最终答案。
补充理解
- 怎么从方程转移到凸包的?
假设要求最小的 \(dp\) 值,那等价于求 最小的\(B(i)\)。\(B(i)=Y(j)-K(i)\times X(j)\),若当前有两个决策点 \(j,k\),且满足 \(j<k\)。当 \(k\) 比 \(j\) 更优时,满足
化简后:
现在转化成了斜率的式子。当转化成这个式子之后,你在二维坐标系上面画图,如果有一个向上凹进去点,一定不是最优的。
- 所有的所有都要建立在 \(X(j)\) 递增上。
化简要用除法,不等式用除法要注意符号,这解释了为什么要满足决策点的 \(X\) 有单调性。另一种理解,如果 \(X(j)\) 不递增,你加入凸包的时候就不是在维护凸包的那个队列末尾加值。不满足单调性时,要用CDQ分治。看这道题
- 怎么判断 下凸包 还是 上凸包?
假设我们设的 \(B(i)\) 当中 \(dp_i\) 的系数为正(如果为负数可以全部都乘 \(-1\) 转化一下)。如果要找 \(dp\) 最小值,就维护下凸包,否则维护上凸包。因为你看之前推的式子,第一步就是写出 \(k\) 比 \(j\) 更优的不等式,上面写的是求 \(dp\) 最小值,如果求最大值无非就是把小于号都变成大于号。
- 关于决策单调性
什么是决策单调性?决策点单调递增
当问题有 决策单调性 的时候,可以用单调队列。没有决策单调性?还是正常用队列维护凸包,但是用二分找最优决策点。怎么判断有没有决策单调性?看 \(K(i)\) 是否有单调性即可。
凸包的维护:
根据上文的两个单调性,判断出选择哪一种维护凸包的方式
- 队列。条件:满足 \(X(j)\) 单调递增。
- 单调队列。条件:满足 \(X(j)\) 单调递增,决策点单调递增。
- 李超线段树。(适用于 \(X(j)\) 不单调递增。也可以用 CDQ 分治来做)
细节
-
关于两个点之间的斜率式子:如果 \(X(j)\) 不是严格单调递增。可能出现两个 \(X\) 相等的情况,所以你的求斜率式子要这么写:
inline ld k(int i,int j){ if(X(i)==X(j)) return (Y(j)>Y(i)?(ld)INF:(ld)-INF); return (ld)1.0*(Y(i)-Y(j))/((ld)1.0*(X(i)-X(j))); }注意到了吗?当 \(i,j\) 顺序不同的时候可能会返回不一样的值哦(\(X\) 相等的情况),所以在调用这个函数的时候,要保证 \(i<j\)。如果你不这么写,会获得WA100的好成绩
-
关于CDQ分治:先按 \(k(i)\) 排序。处理区间 \([l,r]\) 时,先递归处理 \([l,mid]\),然后计算 \([l,mid]\) 区间内的元素对 \([mid+1,r]\) 区间内元素的贡献,就是先把左边的所有元素加到维护凸包的队列里面(边加边维护),然后再更新 \(dp_i(mid<i\leq r)\) 时,依次删除队头。递归处理 \([mid+1,r]\)。然后再按 \(X\) 的值对 \([l,r]\) 排序(可以使用归并排序)。解释:因为处理完 \([l,r]\) 后,\([l,r]\) 区间内的元素是按 \(X\) 排序,所以在计算 \([l,mid]\) 区间内的元素对 \([mid+1,r]\) 区间内元素的贡献时,左边区间满足 \(X\) 单调递增,右边区间还没有被处理,所以满足 \(k\) 单增,也就是满足决策单调性。更具体的解释还是看参考博客qwq
-
维护队列时,不管是删队头(找最优决策点时),还是删队尾时(维护凸包),都要判断队列内的元素是否 \(>1\).只有大于 \(1\) 才有“斜率”这个说法啊,不然只有一个点怎么找斜率。
本文来自博客园,作者:bwartist,转载请注明原文链接:https://www.cnblogs.com/bwartist/p/17550095.html

浙公网安备 33010602011771号