• BZOJ_2726_[SDOI2012]任务安排_斜率优化+二分


    BZOJ_2726_[SDOI2012]任务安排_斜率优化+二分

    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

    设F[i]表示前i个任务完成后最小的代价。
    然后把后面的代价提前计算。
    设sx[],sy[]分别为x,y的前缀和。
    F[i]=F[j]+(m+sx[i]-sx[j])*(sy[n]-sy[j])。设sum=sy[n]。
    然后斜率优化:F[i]=-sy[j]*sx[i]  -sx[j]*sum-m*sy[j]+sx[j]*sy[j]  +m*sum+sx[i]*sum
    把决策点当成直线,斜率-sy[j]单调减。
    于是维护一个上凸壳。
    但是每次查询的X(i)=sx[i]不一定单调。
    因此不能乱弹队首。每次二分一下当前凸壳上交点离X(i)最近的大于X(i)位置,这个位置最优。
     
    代码:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    #define N 300050
    int n,m,xx[N],yy[N],Q[N],l,r;
    ll f[N],sx[N],sy[N],sum;
    ll K(int j) {
        return -sy[j];
    }
    ll B(int j) {
        return f[j]-sx[j]*sum-m*sy[j]+sx[j]*sy[j];
    }
    ll Y(int i,int j) {
        return K(j)*sx[i]+B(j);
    }
    bool cover(int p1,int p2,int p3) {
        // return (K(p1)-K(p3))*(B(p2)-B(p1))>=(K(p1)-K(p2))*(B(p3)-B(p1));
        return (K(p2)-K(p3))*(B(p1)-B(p3))<=(B(p3)-B(p2))*(K(p3)-K(p1));
    }
    bool check(int p1,int p2,int i) {
        return B(p1)-B(p2)>=sx[i]*(K(p2)-K(p1));
    }
    int main() {
        scanf("%d%d",&n,&m);
        int i,j;
        for(i=1;i<=n;i++) {
            scanf("%d%d",&xx[i],&yy[i]);
            sx[i]=sx[i-1]+xx[i];
            sy[i]=sy[i-1]+yy[i];
        }
        sum=sy[n];
        memset(f,0x3f,sizeof(f));
        f[0]=0;
        /*for(i=1;i<=n;i++) {
            for(j=0;j<i;j++) {
                f[i]=min(f[i],f[j]+(m+sx[i]-sx[j])*(sum-sy[j]));
            }
        }*/
        r=1;
        /*for(i=1;i<=n;i++) {
            while(l<r-1&&Y(i,Q[l])>=Y(i,Q[l+1])) l++;
            j=Q[l];
            printf("%d
    ",j);
            f[i]=Y(i,j)+m*sum+sx[i]*sum;
            while(l<r-1&&cover(Q[r-2],Q[r-1],i)) r--;
            Q[r++]=i;
        }*/
        for(i=1;i<=n;i++) {
            int ll=l,rr=r-1;
            while(ll<rr) {
                int mid=(ll+rr)>>1;
                if(check(Q[mid],Q[mid+1],i)) ll=mid+1;
                else rr=mid; 
            }
            j=Q[ll];
            //printf("%d
    ",j);
            f[i]=Y(i,j)+m*sum+sx[i]*sum;
            while(l<r-1&&cover(Q[r-2],Q[r-1],i)) r--;
            Q[r++]=i;
        }
        printf("%lld
    ",f[n]);
    }
    
  • 相关阅读:
    DedeCMS的arclist循环中判断第一个元素并添加class样式
    PC 浏览器伪装移动(微信)User-Agent
    DedeCMS后台无法保存中文字符
    java spring boot 定时器
    java spring boot 部署redis
    java spring boot 打包方法
    java spring boot返回json的写法
    关于java idea 创建spring boot没有下载依赖的解决方案
    java和golang并发测试
    php转java 系列2 Spring boo 链接数据库jdbc
  • 原文地址:https://www.cnblogs.com/suika/p/9202132.html
Copyright © 2020-2023  润新知