[ZJOI2007] 仓库建设

大脑真是个很优秀的器官,做事情之前总会想着这太难,真的逼着自己做下去,回头看看,其实也不过如此

很朴素的斜率优化dp了

首先要读懂题目(我的理解能力好BUG啊)

然后设(dp[i])表示处理完前(i)个家伙,并且在第(i)个家伙处建仓的答案

那么有

[dp[i] = min_{j=1}^{i-1}{dp[j] + sum_{k=j+1}^{i-1} p[k] * (x[i] - x[k])} + c[i] ]

化简发现,优劣比较条件为

[frac{dp[p]-dp[q]+t[p]-t[q]}{s[p]-s[q]} < x[i] ]

于是就皆大欢喜啦

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;

int n,x[N],p[N],c[N],s[N],t[N],f[N],q[N],l,r;

double slope(int k,int j) {
    return 1.0 * (f[j]+t[j]-f[k]-t[k]) / (s[j]-s[k]);
}

signed main() {
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) {
        scanf("%lld%lld%lld",&x[i],&p[i],&c[i]);
        s[i]=s[i-1]+p[i];
        t[i]=t[i-1]+x[i]*p[i];
    }
    l=1; r=1;
    for(int i=1;i<=n;i++) {
        while(l<r && slope(q[l],q[l+1]) <= x[i]) ++l;
        int j=q[l];
        f[i] = f[j]+x[i]*(s[i]-s[j])-t[i]+t[j]+c[i];
        while(l<r && slope(q[r-1],q[r]) >= slope(q[r],i)) --r;
        q[++r]=i;
    }
    cout<<f[n]<<endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/12257355.html