斜率优化DP
先对土地按照长和宽进行排序,把长和宽被包括的土地(即对于土地
i
,存在土地
设
f[i]
表示以
i
为结尾的土地所需的最小代价,则
即把j+1~i进行合并。
但是这样是
n2
的,注意到有
x[i]∗y[j+1]
存在,那么考虑斜率优化。
下面是我的推导过程:
f[x]+x[i]∗y[x+1]<f[y]+x[i]∗y[y+1]
f[x]−f[y]<x[i]∗(y[y+1]−y[x+1])
f[x]−f[y]y[y+1]−y[x+1]>x[i] ( x<y 时 y[y+1]<y[x+1] )
单调队列维护左边的式子即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 50000
using namespace std;
typedef long long LL;
struct lnd{
LL x,y;
}a[MAXN+5],b[MAXN+5],c[MAXN+5];
int na,nb,n,r,w,que[MAXN+5];
LL f[MAXN+5];
bool cmp(lnd x,lnd y){
return x.x<y.x||(x.x==y.x&&x.y<y.y);
}
LL K(int x,int y){
return (f[x]-f[y])/(c[y+1].y-c[x+1].y);
}
int main(){
scanf("%d",&na);
for (int i=1;i<=na;i++)
scanf("%lld%lld",&a[i].x,&a[i].y);
sort(a+1,a+na+1,cmp);
for (int i=1;i<=na;i++){
while (n&&a[i].y>=c[n].y) n--;
c[++n]=a[i];
}
for (int i=1;i<=n;i++){
while (r<w&&K(que[r],que[r+1])<c[i].x)
r++;
f[i]=f[que[r]]+c[i].x*c[que[r]+1].y;
while (r<w&&K(que[w-1],que[w])>=K(que[w],i)) w--;
que[++w]=i;
}
return printf("%lld\n",f[n]),0;
}