1597: [Usaco2008 Mar]土地购买
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3739 Solved: 1376
[Submit][Status][Discuss]
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
100 1
15 15
20 5
1 100
Sample Output
500
【题解】
按照x,y递增排序,然后把可以和其它打包一起买的去掉
然后使得剩下一些y递减x递增的矩形
显然f[i]=min(f[j]+y[j+1]x[i])
然后再搞个斜率优化
方程是(f[j]-f[k])/(y[k+1]-y[j+1])<x[i]
然后维护一个下凸包
——转自hzwer
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<ctime> 6 #include<cmath> 7 #include<algorithm> 8 using namespace std; 9 typedef long long ll; 10 #define MAXN 50010 11 #define FILE "read" 12 #define up(i,j,n) for(ll i=j;i<=n;i++) 13 namespace INIT{ 14 char buf[1<<15],*fs,*ft; 15 inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;} 16 inline ll read(){ 17 ll x=0,f=1; char ch=getc(); 18 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();} 19 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();} 20 return x*f; 21 } 22 }using namespace INIT; 23 struct node{ll x,y;}a[MAXN]; 24 ll n,len,head,tail,x[MAXN],y[MAXN],f[MAXN],q[MAXN]; 25 bool cmp(node a,node b) {return a.x==b.x?a.y<b.y:a.x<b.x;} 26 void init(){ 27 n=read(); 28 up(i,1,n) a[i].x=read(),a[i].y=read(); 29 sort(a+1,a+n+1,cmp); 30 up(i,1,n){ 31 while(len&&a[i].y>=y[len]) len--; 32 x[++len]=a[i].x; y[len]=a[i].y; 33 } 34 } 35 inline double slop(ll j,ll k) {return (double)(f[j]-f[k])/(double)(y[k+1]-y[j+1]);} 36 void solve(){ 37 up(i,1,len){ 38 while(head<tail&&slop(q[head],q[head+1])<x[i]) head++; 39 ll t=q[head]; 40 f[i]=f[t]+y[t+1]*x[i]; 41 while(head<tail&&slop(q[tail-1],q[tail])>slop(q[tail],i)) tail--; 42 q[++tail]=i; 43 } 44 printf("%lld ",f[len]); 45 } 46 int main(){ 47 freopen(FILE".in","r",stdin); 48 freopen(FILE".out","w",stdout); 49 init(); 50 solve(); 51 return 0; 52 }