土地購買(USACO 2008 March Gold)
阿新 • • 發佈:2018-12-18
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; }