这题,一道神奇的,斜率优化DP。。。柿子为什么辣么难写啊!!!!!!!!!!
自己懒得手打了,引用一下别人的柿子。。。
dp[i]=min(dp[i],dp[j]+c[i]+∑(x[i]-x[j])*p[j])
s[i]=x[1]*p[1]+x[2]*p[2]+...+x[i]*p[i]
a[i]=p[1]+p[2]+...+p[i]
dp[i]=min(dp[i],dp[j]+c[i]-x[i]*(a[j]-a[i])-(s[i]-s[j]))
然后经过一同化柿子。。。就出来了。。。QAQ。。。
还要注意一点。。。这个柿子。。。最后化成斜率式的时候。。。
要计算成double。。。否则会出现精度问题(luoguAC BZOJWA)
呆码:
#include<iostream> #include<cstdio> #include<cstring> #define N 1000010 #define ll long long using namespace std; ll f[N],s[N],a[N]; ll q[N],c[N],p[N],x[N]; int n; inline double doit(int i,int j) { return (f[j]+s[j]-f[i]-s[i])/(a[j]-a[i]); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d%d",&x[i],&p[i],&c[i]); for(int i=1;i<=n;i++) { s[i]=s[i-1]+x[i]*p[i]; a[i]=a[i-1]+p[i]; } memset(f,50,sizeof(f)); f[0]=0; int head=0,tail=0; for(int i=1,j;i<=n;i++) { while(head<tail && x[i]>doit(q[head],q[head+1])) head++; j=q[head]; f[i]=f[j]+c[i]-x[i]*(a[j]-a[i])-s[i]+s[j]; while(head<tail && doit(q[tail],i)<doit(q[tail-1],q[tail])) tail--; q[++tail]=i; } printf("%lld",f[n]); }