您的位置:首页 > 其它

bzoj1597 土地购买

2016-01-19 19:55 309 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: