ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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;
}

 

posted on 2016-01-19 19:55  nul  阅读(183)  评论(0编辑  收藏  举报