bzoj 2726 任务安排
题目大意:
机器上有N个需要处理的任务,它们构成了一个序列 把这些任务分成若干批
从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti
在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和
注意,同一批任务将在同一时刻完成 每个任务的费用是它的完成时刻乘以一个费用系数Fi
请确定一个分组方案,使得总费用最小
思路:
设dp数组表示前i个的最小花费 为了方便统计 顺便加上对后面的影响
dp i = dpj +(sumtime i - sumtime j + s) * (sumcost n -sumcost j)
拆开之后斜率优化
注意到时间有可能是负的 因此斜率不单调 需要二分
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 1001000 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 ll st[MAXN],sc[MAXN],f[MAXN]; 22 int n,s,tim,hd,tl,q[MAXN]; 23 ll Y(int i) {return f[i]-sc[n]*st[i]+sc[i]*st[i]-sc[i]*tim;} 24 int main() 25 { 26 n=read(),tim=read(); 27 for(int i=1;i<=n;i++) st[i]=st[i-1]+read(),sc[i]=sc[i-1]+read(); 28 for(int i=1;i<=n;i++) 29 { 30 int l=0,r=tl-1,res=tl,j; 31 while(l<=r) 32 { 33 int mid=(l+r)>>1; 34 if(1ll*(sc[q[mid+1]]-sc[q[mid]])*st[i]<=Y(q[mid+1])-Y(q[mid])) res=mid,r=mid-1; 35 else l=mid+1; 36 } 37 j=q[res],f[i]=f[j]+(sc[n]-sc[j])*(st[i]-st[j]+tim); 38 while(hd<tl&&1ll*(Y(q[tl])-Y(q[tl-1]))*(sc[i]-sc[q[tl]])>=(Y(i)-Y(q[tl]))*(sc[q[tl]]-sc[q[tl-1]])) tl--; 39 q[++tl]=i; 40 } 41 printf("%lld\n",f[n]); 42 }