zoukankan      html  css  js  c++  java
  • BZOJ2726 SDOI2012 任务安排

    题目

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

    思路

    首先显然是(dp)划分状态。

    [dp[i]=min(dp[j]+t[i]*(f[i]-f[j])+s*f[n]-s*f[j]) ]

    不难看出可以斜率优化。

    然而不知道出题人怎么想的,时间竟然可以出现负数,这样对于(x)不单调的斜率优化,就只能用CDQ分治维护凸包。

    具体而言,就是和惯常的CDQ分治一样,分别将([l,mid]),([mid+1,r])区间排序,([l,mid])建一个凸包,回答([mid+1,r])的询问。

    一个while打成if调了一个晚上

    代码

    #include<bits/stdc++.h>
    #define M 300005
    #define LL long long
    using namespace std;
    LL t[M],f[M],dp[M],s;
    int n,qcnt,tcnt,top;
    struct node{
        LL x,y;
        bool operator < (const node& res)const{
            if(x!=res.x)return x<res.x;
            return y>res.y;
        }
    }Q[M],stk[M],to[M];
    bool cmp(node a,node b,node c){
        return (long double)(c.y-a.y)*(a.x-b.x)<=(long double)(a.y-b.y)*(c.x-a.x);
    }
    LL calc(int cur,int i){
        return  (long double)stk[cur].y-(long double)t[to[i].y]*stk[cur].x+(long double)t[to[i].y]*f[to[i].y]+(long double)s*f[n];
    }
    void CDQ(int l,int r){
        if(l==r)return;
        int mid=(l+r)>>1;
        CDQ(l,mid);qcnt=0;
        for(int i=l;i<=mid;i++)
            Q[++qcnt]=(node){f[i],dp[i]-s*f[i]};
        sort(Q+1,Q+qcnt+1);top=0;
        for(int i=1;i<=qcnt;i++){
            while(top>1&&cmp(stk[top],stk[top-1],Q[i]))top--;
            stk[++top]=Q[i];
        }
        tcnt=0;
        for(int i=mid+1;i<=r;i++)
            to[++tcnt]=(node){t[i],i};
        sort(to+1,to+tcnt+1);
        int cur=1;
        for(int i=1;i<=tcnt;i++){
            while(cur<top&&calc(cur+1,i)<calc(cur,i))cur++;
            dp[to[i].y]=min(dp[to[i].y],calc(cur,i));
        }
        CDQ(mid+1,r);
    }
    int main(){
        memset(dp,60,sizeof(dp));dp[0]=0;
        scanf("%d%lld",&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];
        }
        CDQ(0,n);
        printf("%lld
    ",dp[n]);
        return 0;
    }
    
  • 相关阅读:
    Redis涉及的概念
    Redis高级教程
    Redis基础入门
    Java多线程面试题
    Java集合面试题
    Java集合基础
    Java基础面试题总结
    Zookeeper Basics
    GitLab基础入门
    阿里云ECS服务器Docker安装Tomcat过程记录
  • 原文地址:https://www.cnblogs.com/zryabc/p/11232182.html
Copyright © 2011-2022 走看看