您的位置:首页 > 其它

土地购买[Usaco2008 Mar][bzoj 1597]

2016-07-01 12:42 288 查看

问题描述 Problem Description

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

输入描述 Input Description

第 1 行: 一个数: N

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

输出描述 Output Description

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

样例输入 Sample Input

4

100 1

15 15

20 5

1 100

样例输出 Sample Output

500

数据范围及提示 Data Size & HINT

FJ分 3 组买这些土地: 第一组: 100∗1 , 第二组 1∗100 , 第三组 20∗5 和 15∗15 . 每组的价格分别为 100,100,300 , 总共 500.

分析 I Think

第 i 块地的长为 li ,宽为 wi 。

因为如果存在两块地,使得 li≤lj,wi≤wj,那么在购买的时候可以把他们放在一组, 土地 i 不用花钱了。根据这一点可以去除一些免费的土地,使得剩下的土地排序后 l 单调递减, w 单调递增。

依据题意可以得出 fi=min{fj+lj∗wi}

考虑当 k<j ,决策 j 比决策 k 更优的条件,即 fj+lj∗wi≤fk+lk∗wi。所以 fj−fklk−lj≤wi ,就是斜率优化了。

代码 Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;

struct rec{LL a,b;bool operator < (const rec &h)const{return a<h.a||(a==h.a&&b<h.b);}}area[50010],a[50010];
int que[50010],H,T;
LL f[50010];
int n,N;

LL x(int,int);
LL y(int,int);

int main(){

scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%lld%lld",&area[i].a,&area[i].b);

sort(area+1,area+n+1);

a[N=1] = area
;
for(int i=n-1;i>=1;--i)
if(area[i].b > a
.b)
a[++N] = area[i];

que[H=0] = 0;
T = 1;

for(int i=1;i<=N;++i){

while(H+1<T && y(que[H+1],que[H])<=x(que[H+1],que[H])*a[i].b)
++H;
f[i] = f[que[H]]+a[que[H]+1].a*a[i].b;
while(H+1<T && y(i,que[T-1])*x(que[T-1],que[T-2])<=y(que[T-1],que[T-2])*x(i,que[T-1]))
--T;
que[T++] = i;

}

printf("%lld",f
);

return 0;

}

LL x(int i,int j){

return a[j+1].a-a[i+1].a;

}

LL y(int i,int j){

return f[i]-f[j];

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