1597: [Usaco2008 Mar]土地购买

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

HINT

 

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

 
第一次写GLOD。。。
做了两道题终于对斜率优化有了比较深刻的理解。。。虽然过程很艰难=,=
这道题首先很容易想到如果一块土地的长宽全部小于另一块,那么这块土地就没什么用处。。。
所以我首先排了下序,然后发现如果长(或宽)递增,去掉没有用的土地,剩下的土地的宽(或长)是递减的。。。
那么就可以发现这样的话,只需要确定一组土地的第一块和最后一块,那么中间的土地就不用管了。。。
因此得到转移方程:F[i]=min(F[j]+x[j+1]*y[i])
一般枚举i,j的话是O(n^2),这里的n是50000,会T。。。所以考虑优化。。。
如果决策点j比k优的话:
F[j]+x[j+1]*y[i]<F[k]+x[k+1]*y[i]
化简,得:y[i]*(x[j+1]-x[k+1])<F[k]-F[j]
很明显,是斜率优化。。。然后就可以做出来了。。。
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #include<string>
 8 #include<map>
 9 #include<queue>
10 #include<vector>
11 #include<set>
12 #define inf 1000000000
13 #define maxn 50000+5
14 #define maxm 10000+5
15 #define eps 1e-10
16 #define ll long long
17 #define for0(i,n) for(int i=0;i<=(n);i++)
18 #define for1(i,n) for(int i=1;i<=(n);i++)
19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
22 using namespace std;
23 struct size{
24     ll x,y;
25 }w[maxn];
26 size a[maxn];
27 ll f[maxn];
28 int q[maxn];
29 bool cmp(size a,size b){
30     if(a.x==b.x) return a.y>b.y;
31     else return a.x>b.x;
32 }
33 int read(){
34     int x=0,f=1;char ch=getchar();
35     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
36     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
37     return x*f;
38 }
39 ll k(ll x,ll y){
40     return    a[y+1].x-a[x+1].x;
41 }
42 ll s(ll x,ll y){
43     return    f[x]-f[y];
44 }
45 int main(){
46     int n=read();
47     for1(i,n){w[i].x=read();w[i].y=read();}
48     sort(w+1,w+n+1,cmp);
49     int tot=0;
50     for1(i,n){
51         if(w[i].x<=a[tot].x&&w[i].y<=a[tot].y)continue;
52         a[++tot].x=w[i].x;
53         a[tot].y=w[i].y;
54     }
55     int l=0,r=0;
56     for1(i,tot){
57         while(l<r&&a[i].y*k(q[l],q[l+1])<s(q[l],q[l+1]))l++;
58         f[i]=f[q[l]]+a[q[l]+1].x*a[i].y;
59         while(l<r&&k(i,q[r])*s(q[r],q[r-1])>k(q[r],q[r-1])*s(i,q[r]))r--;
60         q[++r]=i; 
61     }
62     //for1(i,tot)cout<<f[i]<<endl;
63     cout<<f[tot]<<endl;
64     return 0;
65 }
View Code

 

 
posted @ 2016-02-12 17:29  HTWX  阅读(107)  评论(0编辑  收藏  举报