您的位置:首页 > 其它

[bzoj1597][Usaco2008 Mar]土地购买

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

题解:先排序一下去掉没用的矩形,然后就可以斜率优化啦。

f[i]=min(f[j]+b[j+1]*a[i])

f[j]+b[j+1]*a[i]<f[k]+b[k+1]*a[i]

$a[i] > \frac{f[j]-f[k]}{b[k+1]-b[j+1]}$

#include<iostream>
#include<cstdio>
#include<algorithm>
#define MN 50000
#define ll long long
#define int long long
using namespace std;
inline int read()
{
int x = 0 , f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}

int n,m;
struct sq{int a,b;}s[MN+5],l[MN+5];
ll f[MN+5];
bool cmp(sq x,sq y){return x.a<y.a||(x.a==y.a&&x.b<y.b);}
int q[MN+5],top,tail;

double calc(int x,int y)
{
return (double)(f[x]-f[y])/(s[x+1].b-s[y+1].b);
}

int get(int x)
{
while(top>tail&&-x<calc(q[tail+1],q[tail])) tail++;
return q[tail];
}

void ins(int x)
{
while(top>tail&&calc(x,q[top])>calc(q[top],q[top-1]))--top;
q[++top]=x;
}

main()
{
n=read();
for(int i=1;i<=n;i++)l[i].a=read(),l[i].b=read();
sort(l+1,l+n+1,cmp);
for(int i=1;i<=n;i++)
{
while(m&&l[i].b>=s[m].b) --m;
s[++m]=l[i];
}
q[top=tail=1]=0;//f[1]=1LL*s[1].a*s[1].b;
for(int i=1;i<=m;i++)
{
int from=get(s[i].a);
f[i]=f[from]+1LL*s[from+1].b*s[i].a;
ins(i);
}
cout<<f[m];
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: