BZOJ 1096: [ZJOI2007]仓库建设(DP+斜率优化)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define maxn 1000100
#define ll long long
#define dd double
int n;
ll x[maxn],p[maxn],c[maxn];
ll X[maxn],P[maxn],C[maxn],A[maxn];
ll f[maxn],yy[maxn];
int qu[maxn],he,bo;
ll a1[maxn],a2[maxn],a3[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld%lld",&a1[i],&a2[i],&a3[i]);
}
for(int i=1;i<=n;i++){
x[i]=a1[n]-a1[n-i+1];
p[i]=a2[n-i+1];
c[i]=a3[n-i+1];
}
n++;
x[n]=x[n-1];
for(int i=1;i<=n;i++){
X[i]=x[i],P[i]=P[i-1]+p[i];
A[i]=A[i-1]+p[i]*X[i];
}
f[1]=c[1];
yy[1]=c[1]-A[1]+X[1]*P[1];
qu[he=bo=1]=1;
for(int i=2;i<=n;i++){
while(he>bo&&yy[qu[bo+1]]-yy[qu[bo]]<=(X[qu[bo+1]]-X[qu[bo]])*(P[i-1])){
bo++;
}
f[i]=yy[qu[bo]]+c[i]+A[i-1]-X[qu[bo]]*P[i-1];
yy[i]=f[i]-A[i]+X[i]*P[i];
while(he>bo&&(yy[qu[he]]-yy[qu[he-1]])*(X[i]-X[qu[he]])>=(yy[i]-yy[qu[he]])*(X[qu[he]]-X[qu[he-1]]))he--;
qu[++he]=i;
}
cout<<f[n];
}