1. 程式人生 > >土地購買(USACO 2008 March Gold)

土地購買(USACO 2008 March Gold)

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

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

Sample Input

4

100 1

15 15

20 5

1 100

輸入解釋:共有4塊土地.

Sample Output

500 輸出解釋:FJ分3組買這些土地: 第一組:100x1, 第二組1x100, 第三組20x5 和 15x15 plot. 每組的價格分別為100,100,300, 總共500.

顯然,對於(x1,y1),(x2,y2),如果x1>=x2&&y1>=y2,那麼(x2,y2)是沒有任何用處的,所以我們可以篩出x單調y單調的序列,然後我們就可以斜率優化了。

#include<bits/stdc++.h>
using namespace std;
const int Maxn=50005;
#define int long long
struct land{
	int x,y;
	bool operator <(const land&rhs)const{
		return x>rhs.x||x==rhs.x&&y>rhs.y;
	}
}a[Maxn],s[Maxn];
int n,cnt,f[Maxn];
int l,r,q[Maxn];
//f[i]=min(f[i],f[j]+s[j+1].x*s[i].y);
#define T(x1,x2) (1.0*(f[x1]-f[x2]))/(1.0*(s[x2+1].x-s[x1+1].x))
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;++i){
		scanf("%lld%lld",&a[i].x,&a[i].y);
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;++i){
		if(a[i].y<=s[cnt].y)continue;
		s[++cnt]=a[i];
	}
	f[q[l=r=1]=0]=0;
	for(int i=1;i<=cnt;++i){
		while(l<r&&T(q[l],q[l+1])<=s[i].y)++l;
		f[i]=f[q[l]]+s[i].y*s[q[l]+1].x;
		while(l<r&&T(q[r-1],q[r])>=T(q[r],i))--r;
		q[++r]=i;
	}
	cout<<f[cnt]<<endl;
	return 0;
}