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
",f[n]);
42 }
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9838364.html