bzoj 2726: [SDOI2012]任务安排

来源:互联网 发布:工业自动化仿真软件 编辑:程序博客网 时间:2024/05/22 03:11

Description

机器上有N个需要处理的任务,它们构成了一个序列。这些任务被标号为1到N,因此序列的排列为1,2,3...N。这N个任务被分成若干批,每批包含相邻的若干任务。从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti。在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和。注意,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数Fi。请确定一个分组方案,使得总费用最小。

Input

第一行两个整数,N,S。
接下来N行每行两个整数,Ti,Fi。

Output

一个整数,为所求的答案。

Sample Input

5 1
1 3
3 2
4 3
2 3
1 4

Sample Output

153


这题完成的时间是有负数的,但是似乎费用系数Fi没负数。

明明两个输入的描述是一样的。。也不知道出题人在想什么。。或者说毕竟SDOI么

我们考虑从后往前转移 F,T均为后缀和

f[i]=min(f[j]+(Ti-Tj+S)*Fi)

大概这样一个转移式。

假设j<k,j比k优,

即f[j]+(Ti-Tj+S)*Fi<f[k]+(Ti-Tk+S)*Fi

移项后得

f[j]-f[k]<Fi*(Tj-Tk)

因为T不是单调的所以没办法做除法。

我们考虑cdq分治

假设当前区间是[l,r]

则先把[mid,r]的答案处理出来,然后把[mid,r]中的T按照升序排序

这样就保证了T的单调性,暴力维护出凸壳

然后对于[l,mid],因为F是单调的,所以直接顺着凸壳扫过去找到最优转移位置就可以了

#include<cstdio>#include<string>#include<cstring>#include<algorithm>using namespace std;struct quest{long long t,f;long long fx;int p;}a[300005],b[300005];inline bool cmp(quest x,quest y){return x.p<y.p;}int q[300005];long long f[300005];long long s;inline bool check(int x,int y,int z){return (a[z].t-a[y].t)*(a[y].fx-a[x].fx)>=(a[z].fx-a[y].fx)*(a[y].t-a[x].t);}inline bool getk(int x,int y,long long z){return (a[y].fx-a[x].fx)<z*(a[y].t-a[x].t);}inline long long calc(int x,int i){return a[x].fx+a[i].f*(a[i].t-a[x].t+s);}inline void solve(int ll,int rr){if(ll==rr-1){return ;}int mid=(ll+rr)/2;solve(mid,rr);int i;int l=1,r=0;for(i=rr-1;i>=mid;i--){while(r>1&&check(q[r-1],q[r],i))r--;r++;q[r]=i;}for(i=mid-1;i>=ll;i--){while(l<r&&getk(q[l],q[l+1],a[i].f))l++;a[i].fx=min(a[i].fx,calc(q[l],i));}solve(ll,mid);int d1=rr-1,d2=mid-1;for(i=rr-1;i>=ll;i--){if(d1<=mid-1){b[i]=a[d2];d2--;}else if(d2<=ll-1){b[i]=a[d1];d1--;}else{if(a[d2].t<a[d1].t||a[d2].t==a[d1].t){b[i]=a[d2];d2--;}else{b[i]=a[d1];d1--;}}}for(i=ll;i<=rr-1;i++)a[i]=b[i];}int main(){int n;scanf("%d%lld",&n,&s);int i;for(i=1;i<=n;i++){scanf("%lld%lld",&a[i].t,&a[i].f);a[i].p=i;}for(i=n;i>=1;i--){a[i].t=a[i+1].t+a[i].t;a[i].f=a[i+1].f+a[i].f;a[i].fx=a[i].f*(a[i].t+s);}solve(1,n+1);sort(a+1,a+1+n,cmp);printf("%lld\n",a[1].fx);return 0;}


原创粉丝点击