当动态规划的状态数为\(O(n)\),每个状态的转移数也是\(O(n)\)时,称这种动态规划为1D1D动态规划。
对于这种问题,朴素做法是\(O(n^2)\)的。优化方法有不少。
斜率优化
首先证明决策单调性,即带入\(k<j\)进行比较。若式子能够化为斜率的形式,则可以使用斜率优化。
通过斜率我们可以得出每一个状态对应的点,利用决策单调性可以证明出上凸(或下凸)一定不优,由此问题转化为维护下凸(或上凸)。转移点一定是当前斜率对应的凸包顶点。用栈+二分实现即可。
在代码实现上有一些坑
斜率:
inline double slope(int i, int j){
return (Y(i)-Y(j)) * 1.0 / ((X(i)==X(j)) ? -(1e-9) : (X(i)-X(j)));
}
sta[++top] = 0;
for(int i = 1; i <= n; ++i){
p = top;
l = 1, r = top-1;
while(l <= r){
mid = (l+r)>>1;
if(slope(sta[mid],sta[mid+1]) > a[i]){
p = mid;
r = mid-1;
}else{
l = mid+1;
}
}
int j = sta[p];
ans = max(ans,org-a[i]*i+a[i]+a[i]*j+s[i-1]-s[j]);
while(top > 1 && slope(sta[top],i) < slope(sta[top-1],sta[top])) --top;
sta[++top] = i;
}