bzoj 2726 任务安排(3)/loj 10184-10186 斜率优化
任务安排1
#include<bits/stdc++.h> #define int long long using namespace std; const int N=5050; int n,s,t[N],c[N],f[N]; int sumt[N],sumc[N]; signed main(){ scanf("%lld%lld",&n,&s); for(int i=1;i<=n;i++) scanf("%lld%lld",&t[i],&c[i]),sumt[i]=sumt[i-1]+t[i],sumc[i]=sumc[i-1]+c[i]; memset(f,127,sizeof f); f[0]=0; for(int i=1;i<=n;i++){ for(int j=0;j<i;j++) f[i]=min(f[i],f[j]+(sumc[i]-sumc[j])*sumt[i]+s*(sumc[n]-sumc[j])); //利用刷表法,将影响向后累加 } printf("%lld\n",f[n]);return 0; }
任务安排2 数据规模变大
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N=5050; long long f[N],sumt[N],sumc[N]; int q[N],n,s; int main(){ scanf("%d%d",&n,&s); for(int i=1;i<=n;i++){ int t,c; scanf("%d%d",&t,&c); sumt[i]=sumt[i-1]+t; sumc[i]=sumc[i-1]+c; } memset(f,0x3f,sizeof f); f[0]=0; int head=1,tail=1; q[1]=0; for(int i=1;i<=n;i++){ while(head<tail&&f[q[head+1]]-f[q[head]]<=(s+sumt[i])*(sumc[q[head+1]]-sumc[q[head]])) head++; f[i]=f[q[head]]-(sumt[i]+s)*sumc[q[head]]+s*sumc[n]+sumt[i]*sumc[i]; while(head<tail&&(f[q[tail]]-f[q[tail-1]])*(sumc[i]-sumc[q[tail]])>=(f[i]-f[q[tail]])*(sumc[q[tail]]-sumc[q[tail-1]])) tail--; q[++tail]=i; } printf("%d\n",f[n]);return 0; }
任务安排3 T可能是负数
#include<bits/stdc++.h> using namespace std; const int N=300050; long long sumt[N],sumc[N],f[N]; int q[N],n,s,head,tail; int binarysearch(int i,int k){ if(head==tail) return q[head]; int l=head,r=tail; 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(){ cin>>n>>s; for(int i=1;i<=n;i++){ int t,c; cin>>t>>c; sumc[i]=sumc[i-1]+c; sumt[i]=sumt[i-1]+t; } head=tail=1; for(int i=1;i<=n;i++){ int p=binarysearch(i,s+sumt[i]); f[i]=f[p]-(s+sumt[i])*sumc[p]+sumt[i]*sumc[i]+s*sumc[n]; while(head<tail&&(f[q[tail]]-f[q[tail-1]])*(sumc[i]-sumc[q[tail]])>=(f[i]-f[q[tail]])*(sumc[q[tail]]-sumc[q[tail-1]])) tail--; q[++tail]=i; } cout<<f[n]<<endl; return 0; }