BZOJ1096/ZJOI2007/仓库建设

Posted on By 二价氢

状态是一维的而转移是二维的所以用斜率优化DP

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e6+5;
long long f[maxn],g[maxn],w[maxn],x[maxn],a[maxn],b[maxn],c[maxn];
int begin=1,end=0;
int q[maxn];
int n;
int delta(int i,int j)
{
    return x[j]*(a[j]-a[i-1])-b[j]+b[i-1];
}
double k(int i,int j)
{
    return ((double)((f[j-1]+b[j-1])-(f[i-1]+b[i-1])))/((double)(a[j-1]-a[i-1]));
}
int main()
{
    scanf("%d\n",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%lld%lld%lld",&x[i],&w[i],&c[i]);
        b[i]=b[i-1]+x[i]*w[i];
        a[i]=a[i-1]+w[i];
    }
    for (int i=1;i<=n;i++)
    {
        while (begin<end&&(k(g[end-1],i)<k(g[end-1],g[end])))
            end--;
        g[++end]=i;
        while (begin<end&&(k(g[begin],g[begin+1])<x[i]))
            begin++;
        //g[++end]=i;
        f[i]=f[g[begin]-1]+x[i]*a[i]-x[i]*a[g[begin]-1]-b[i]+b[g[begin]-1]+c[i];
    }
    printf("%lld\n",f[n]);
}