# [bzoj] 1597 土地购买 || 斜率优化dp

### 原题

n^2的dp：
dp[i]表示买完前i块土地的最小花费

//按x坐标sort
for (int i=1;i<=n;i++)
for (int j=1;j<i;j++)
dp[i]=min(dp[i],dp[j]+x[i]*y[j+1]);


$dp[j]+x[i]*y[j+1]<dp[k]+x[i]*y[k+1]$

#include<cstdio>
#include<algorithm>
#define N 50010
typedef long long ll;
using namespace std;
struct hhh
{
ll x,y;
bool operator < (const hhh &b) const
{
if (x==b.x) return y<b.y;
return x<b.x;
}
}a[N];
ll n,tot,x[N],y[N],q[N],f[N],l,r;

{
ll ans=0,fu=1;
char j=getchar();
for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
return ans*fu;
}

double check(ll i,ll j)
{
return 1.0*(f[j]-f[i])/(y[i+1]-y[j+1]);
}

int main()
{
sort(a+1,a+n+1);
for (ll i=1;i<=n;i++)
{
while (tot && a[i].y>=y[tot]) tot--;
x[++tot]=a[i].x;
y[tot]=a[i].y;
}
for (ll i=1;i<=tot;i++)
{
while (l<r && check(q[l],q[l+1])<x[i]) l++;
f[i]=f[q[l]]+y[q[l]+1]*x[i];
while (r>l && check(q[r],i)<check(q[r-1],q[r])) r--;
q[++r]=i;
}
printf("%lld\n",f[tot]);
return 0;
}

posted @ 2018-01-31 16:08  Mrha  阅读(112)  评论(0编辑  收藏  举报