您的位置:首页 > 其它

[斜率DP优化]BZOJ 1597: [Usaco2008 Mar]土地购买 题解

2017-10-20 11:46 519 查看
(传送门)

题目描述

给出n块土地,第i块长度为xi,宽度为yi,一次可以购买任意数目土地,每次购买的价格为所有这次购买的土地中max{xi}∗max{yi},求购买全部土地最少需要多少钱。

解题分析

首先对于一块土地i,如果存在另一块土地j,有xj>xi,yj>yi,那么说明i不可能对答案会有影响,所以可以筛去i,所以可以预处理所有的土地,筛去所有不符合规格的,剩下的土地才是我们要考虑的有可能会对答案产生影响的。这个土地序列满足xi递减yi递增。

然后发现是线性DP,f[i]=min{f[j]+y[i]∗x[j+1]},然后又发现i和j关系有相乘的,就考虑线性DP。

f[j]+y[i]∗x[j+1]<f[k]+y[i]∗x[k+1]

f[j]−f[k]<y[i]∗(r[k+1]−r[j−1])

f[j]−f[k]r[k+1]−r[j+1]<c[i]

然后就直接套模板就行了。

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
struct data{
int x,y;
bool operator < (const data b)const{
return x>b.x||(x==b.x&&y>b.y);
}
}a[50005];
int n,m,que[50005],hed,til;
LL f[50005];
inline void readi(int &x){
x=0; char ch=getchar();
while ('0'>ch||ch>'9') ch=getchar();
while ('0'<=ch&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
}
LL getX(const int i,const int j){return a[i+1].x-a[j+1].x;}
LL getY(const int i,const int j){return f[j]-f[i];}
int main()
{
freopen("buy.in","r",stdin);
freopen("buy.out","w",stdout);
readi(m); n=hed=til=0;
for (int i=1;i<=m;i++) {readi(a[i].x); readi(a[i].y);} sort(a+1,a+m+1);
for (int i=1,mx=0;i<=m;i++) if (mx<a[i].y) {mx=a[i].y; a[++n]=a[i];}
hed=til=1; que[1]=f[0]=0;
for (int i=1;i<=n;i++){
while (hed<til&&getY(que[hed],que[hed+1])<=getX(que[hed],que[hed+1])*a[i].y) hed++;
f[i]=f[que[hed]]+(LL)a[i].y*a[que[hed]+1].x;
while (hed<til&&getY(que[til-1],que[til])*getX(que[til],i)>=getX(que[til-1],que[til])*getY(que[til],i)) til--;
que[++til]=i;
}
printf("%lld\n",f
);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: