bzoj1096: [ZJOI2007]仓库建设
斜率优化dp。
不想写表达式。。。。
s[i]维护前缀p,sx[i]维护前缀p*x。
这样将原dp转移方程转化为了
f[i]=f[j]+(s[i-1]-s[j])x[i]-(sx[i-1]-sx[j])+c[i]。
斜率优化,当i决策时,j>k且j优于k则 x[i]>(f[j]-f[k]+sx[j]-sx[k])/(s[j]-s[k]).
这样就要维护一个下凸包。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1000000 + 10; long long x[maxn],p[maxn],c[maxn]; int n; long long s[maxn],sx[maxn],f[maxn]; int q[maxn],l,r; double slop (int k,int j) { return (f[j]-f[k]+sx[j]-sx[k])/(1.0*(s[j]-s[k])); } int main() { scanf("%d",&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]; sx[i]=sx[i-1]+p[i]*x[i]; } l=0;r=1; for(int i=1;i<=n;i++) { while(l<r-1 && x[i]>slop(q[l],q[l+1])) l++; int t=q[l]; f[i]=f[t]+(s[i-1]-s[t])*x[i]-(sx[i-1]-sx[t])+c[i]; while(l<r-1 && slop(q[r-2],q[r-1]) > slop(q[r-1],i) ) r--; q[r++]=i; } printf("%lld\n",f[n]); return 0; }