Live2d Test Env

luogu2900:Land Acquisition(斜率优化)

题意:有N块地,每块地给出的宽和高,然后可以分批买,每次买的代价是所选择的地种最宽*最高。 问怎么买,使得代价和最小。

思路:显然,先去掉被包括的情况,即如果一个地的宽和高斗比另外一个小,那么久可以删去。 这样,我们得到一些的地宽递增,高递减; 然后得到方程:

dp[i]=min(dp[j]+w[i]*h[j+1]);斜率优化即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
struct in{
    int w,h;
    bool friend operator <(in p,in q){
        return (p.w^q.w)?p.w<q.w:p.h<q.h;
    }
}s[maxn],y[maxn];
ll dp[maxn]; int q[maxn],head,tail;
int main()
{
    int N,M,tot=0;
    scanf("%d",&N);
    rep(i,1,N) scanf("%d%d",&s[i].w,&s[i].h);
    sort(s+1,s+N+1);
    for(int i=N;i>=1;i--){
        if(tot&&y[tot].h>s[i].h) continue;
        y[++tot]=s[i];
    }
    rep(i,1,tot) s[i]=y[tot+1-i];
    N=tot; q[++head]=0;  //tail<=head;
    rep(i,1,N) {
        while(tail<head&&1.0*(dp[q[tail+1]]-dp[q[tail]])/(-s[q[tail+1]+1].h+s[q[tail]+1].h)<1LL*s[i].w) tail++;
        dp[i]=dp[q[tail]]+1LL*s[i].w*s[q[tail]+1].h;
        while(tail<head&&1.0*(dp[i]-dp[q[head]])/(-s[i+1].h+s[q[head]+1].h)<=1.0*(dp[i]-dp[q[head-1]])/(-s[i+1].h+s[q[head-1]+1].h)) head--;
        q[++head]=i;
    }
    printf("%lld\n",dp[N]);
    return 0;
}

 

posted @ 2019-08-01 16:51  nimphy  阅读(309)  评论(0编辑  收藏  举报