题目
与#斜率优化dp# [poj 1180] Batch Scheduling题意相同。
解题思路
我并没有AC。
只是做了任务安排中执行时间可能是负数的情况。
如果执行时间可能是负数的话,那么不具有单调性,从而使斜率也不具有单调性。
所以我们不能只保留凸壳上“连接相邻两点的线段斜率”大于的部分。
而是必须维护整个凸壳。
这样的话,我们就不必要弹出对头,而是在单调队列里用二分查找最优决策。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,s,l,r,t,c,sumt[500001],sumc[500001],q[500001],f[500001];
int binary_search(int i,int k){
if (l==r) return q[l];
int L=l,R=r;
while(L<R){
int mid=(L+R)>>1;
if (f[q[mid+1]]-f[q[mid]]<=k*(sumc[q[mid+1]]-sumc[q[mid]])) L=mid+1; else R=mid;
}
return q[L];
}
int main(){
scanf("%d%d",&n,&s) ;
for(int i=1;i<=n;i++) scanf("%d%d",&t,&c),sumt[i]=sumt[i-1]+t,sumc[i]=sumc[i-1]+c;
l=r=1; q[1]=0;
for(int i=1;i<=n;i++){
int p=binary_search(i,s+sumt[i]);
f[i]=f[p]-(s+sumt[i])*sumc[p]+sumt[i]*sumc[i]+s*sumc[n];
while(l<r&&(f[q[r]]-f[q[r-1]])*(sumc[i]-sumc[q[r]])>=(f[i]-f[q[r]])*(sumc[q[r]]-sumc[q[r-1]])) r--;
q[++r]=i;
}
printf("%d",f[n]);
}