bzoj2726 任务安排

来源:互联网 发布:火箭队实力 知乎 编辑:程序博客网 时间:2024/05/22 06:44

题目:

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

思路:

设f[i]为将前i个任务划分完成的最小费用,Ti Fi分别表示t和f的前缀和,则可以写出转移方程式:
f[i]=min{ f[j]+(F[n]-F[j])*(T[i]-T[j]+s) },1<=j<=i-1
经过整理得到:
f[i]=min{ -T[i]*F[j]+(f[j]-F[n]*T[j]+F[j]*T[j]-s*F[j]) }
设X(i)=F[i],Y(i)=f[j]-F[n]*T[j]+F[j]*T[j]-s*F[j],a(i)=T[i]则有:
f[i]=min{ -a(i)*X(j)+Y(j) }
由于不单调,所以要使用CDQ分治

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<vector>#include<map>#include<set>#include<queue>#include<stack>#include<list>#include<numeric>using namespace std;#define PI acos(-1.0)#define LL long long#define ULL unsigned long long#define INF 0x3f3f3f3f3f3f3f3f#define mm(a,b) memset(a,b,sizeof(a))#define PP puts("*********************");template<class T> T f_abs(T a){ return a > 0 ? a : -a; }template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}// 0x3f3f3f3f3f3f3f3f// 0x3f3f3f3fconst int maxn=5e5+50;struct Node{    LL x,y,k;    int id;    bool operator<(const Node &rhs)const{        return k<rhs.k;    }}q[maxn],tmp[maxn];bool cmp(const Node &a,const Node &b){    if(a.x!=b.x) return a.x<b.x;    return a.y<b.y;}int st[maxn],n,s;LL T[maxn],F[maxn],f[maxn];LL up(int j,int k){    return q[k].y-q[j].y;}LL down(int j,int k){    return q[k].x-q[j].x;}void cdq(int L,int R){    if(L==R){        q[L].x=F[L];        q[L].y=f[L]-F[n]*T[L]+T[L]*F[L]-s*F[L];        return;    }    int mid=(L+R)>>1;    int sz1=L,sz2=mid+1;    for(int i=L;i<=R;i++)        if(q[i].id<=mid) tmp[sz1++]=q[i];        else tmp[sz2++]=q[i];    for(int i=L;i<=R;i++)        q[i]=tmp[i];    cdq(L,mid);    int top=0;    for(int i=L;i<=mid;i++){        while(top>=2&&up(st[top],i)*down(st[top-1],st[top])<up(st[top-1],st[top])*down(st[top],i))            top--;        st[++top]=i;    }    int j=1;    for(int i=mid+1;i<=R;i++){        while(j<top&&up(st[j],st[j+1])<q[i].k*down(st[j],st[j+1]))            j++;        f[q[i].id]=min(f[q[i].id],-q[i].k*q[st[j]].x+q[st[j]].y+F[n]*(T[q[i].id]+s));    }    cdq(mid+1,R);    sz1=L,sz2=mid+1;    for(int i=L;i<=R;i++){        if(sz1<=mid){            if(sz2<=R){                if(cmp(q[sz1],q[sz2])) tmp[i]=q[sz1++];                else tmp[i]=q[sz2++];            }            else                tmp[i]=q[sz1++];        }        else            tmp[i]=q[sz2++];    }    for(int i=L;i<=R;i++)        q[i]=tmp[i];}int main(){//    freopen("D:\\input.txt","r",stdin);//    freopen("D:\\output.txt","w",stdout);    scanf("%d%d",&n,&s);    for(int i=1;i<=n;i++){        scanf("%lld%lld",&T[i],&F[i]);        T[i]+=T[i-1];        F[i]+=F[i-1];    }    for(int i=1;i<=n;i++){        q[i].id=i;        q[i].k=T[i];        f[i]=INF;    }    sort(q+1,q+n+1);    cdq(0,n);    printf("%lld\n",f[n]);    return 0;}


原创粉丝点击