• bzoj1597 土地购买


    Description

    农夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000,000; 1 <= 长 <= 1,000,000). 每块土地的价格是它的面积,但FJ可以同时购买多快土地. 这些土地的价格是它们最大的长乘以它们最大的宽, 但是土地的长宽不能交换. 如果FJ买一块3x5的地和一块5x3的地,则他需要付5x5=25. FJ希望买下所有的土地,但是他发现分组来买这些土地可以节省经费. 他需要你帮助他找到最小的经费.

    Input

    * 第1行: 一个数: N

    * 第2..N+1行: 第i+1行包含两个数,分别为第i块土地的长和宽

    Output

    * 第一行: 最小的可行费用.

    dp斜率优化

    对土地(x1,y1)和(x2,y2),若x1≥x2且y1≥y2,则可忽略(x2,y2)

    将土地按x升序y降序排序,忽略不必考虑的土地

    f[i]=max{f[j]+x[i]*y[j+1]}(0<j<i)

    若k优于j则f[j]-f[k]>x[i]*(y[k+1]-y[j+1])

    #include<cstdio>
    #include<algorithm>
    struct pos{
        long long x,y;
    }vs[50001],ps[50001];
    int pp=1;
    bool operator<(pos a,pos b){
        if(a.x==b.x)return a.y<b.y;
        return a.x<b.x;
    }
    long long f[50001];
    int q[50001]={0};
    int qs=0,qe=0;
    int n;
    inline long long A(int x,int y){
        return f[x]-f[y];
    }
    inline long long B(int x,int y){
        return ps[y+1].y-ps[x+1].y;
    }
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d%d",&vs[i].x,&vs[i].y);
        std::sort(vs,vs+n);
        for(int i=0;i<n;i++){
            while(pp>1&&ps[pp-1].y<=vs[i].y)--pp;
            ps[pp++]=vs[i];
        }
        for(int i=1;i<pp;i++){
            while(qs<qe&&A(q[qs],q[qs+1])>ps[i].x*B(q[qs],q[qs+1]))++qs;
            int w=q[qs];
            f[i]=f[w]+ps[i].x*ps[w+1].y;
            while(qs<qe&&A(q[qe-1],q[qe])*B(q[qe],i)>=A(q[qe],i)*B(q[qe-1],q[qe]))--qe;
            q[++qe]=i;
        }
        printf("%lld",f[pp-1]);
        return 0;
    }
  • 相关阅读:
    Movement Type
    Excel制表技巧
    [转]MM移动类型的配置相关的系统表,举例说明SAP是如何根据配置抛帐的
    Microsoft Excel:Automatically color alternating rows(columns)
    eBook试载(1):Workbook对象与示例(1)
    辨析:would rather 和 prefer
    Serial Number Management In SAP SD
    <摘录>NAL格式
    linux服务简介关闭不需要的Linux服务
    <摘录>PS和TS流的区别
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5143225.html
Copyright © 2020-2023  润新知