有
n
n
块土地需要购买,每块土地都是矩形的,有特定的长与宽。你可以一次性购买一组土地,价格是这组土地中长的最大值乘以宽的最大值。比方说一块5×3的土地和一块9×2的土地在一起购买的价格就是9×3。显然,怎样分组购买土地是一门学问,你的任务就是设计一种方案用最少的钱买下所有的土地,你只需输出最小花费。(土地的宽度记为,长度为y[i])
n≤106
n
≤
10
6
若a矩形包含b矩形,则可将b删去
对于二维偏序问题,可将其中一维先排序
对于这道题就可将x排序
最后x递增,y递减
f[i]=min(f[i],f[j]+x[i]∗y[j+1]); f [ i ] = m i n ( f [ i ] , f [ j ] + x [ i ] ∗ y [ j + 1 ] ) ;
斜率优化
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define File(x) "acquire."#x
#define For(i,s,e) for(int i=(s); i<=(e); i++)
#define Rep(i,s,e) for(int i=(s); i>=(e); i--)
using namespace std;
const int N=50000+15,Mod=1000000007;
typedef long long LL;
struct Node{
LL x,y;
bool del;
bool operator < (const Node & o) const {
return x<o.x;
}
}a[N],b[N];
int n,m;
LL f[N],maxy;
int q[N],tail,front;
LL dy(int i, int j){
return f[i]-f[j];
}
LL dx(int i, int j){
return b[i+1].y-b[j+1].y;
}
int main()
{
freopen(File(in),"r",stdin);
freopen(File(out),"w",stdout);
scanf("%d",&n);
For(i,1,n) scanf("%lld%lld",&a[i].x,&a[i].y), a[i].del=0;
sort(a+1,a+1+n);
Rep(i,n,1){
if(maxy>a[i].y) a[i].del=1;
else maxy=a[i].y;
}
For(i,1,n) if(!a[i].del) b[++m]=a[i];
front=tail=1;
For(i,1,m){
while(front<tail && dy(q[front], q[front+1])>dx(q[front], q[front+1])*(-b[i].x)) front++;
int ch=q[front];
f[i]=f[ch]+b[i].x*b[ch+1].y;
while(front<tail && dy(q[tail-1], i)*dx(q[tail-1], q[tail])>=dy(q[tail-1], q[tail])*dx(q[tail-1], i)) tail--;//维护凸包
q[++tail]=i;
}
printf("%lld\n",f[m]);
return 0;
}