1010: [HNOI2008]玩具装箱toy
//Pro: 1010: [HNOI2008]玩具装箱toy //因为费用为(X-L)^2,所以我们要让X尽量接近L //对于那些c[]>=L的玩具,显然(列式子算一下)一个玩具一个容器最优 //好的不用分开找规律... //斜率优化DP #include<iostream> #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; inline ll read() { char c=getchar();ll num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } const int N=5e4+5; ll n,L,f[N],sum[N],a[N],sqr[N]; ll que[N],head,tail; double calc(ll x,ll y) { return 1.0*(f[y]+sqr[y]-f[x]-sqr[x])/(a[y]-a[x]); } int main() { n=read(),L=read(); sqr[0]=(L+1)*(L+1); for(int i=1;i<=n;++i) { sum[i]=read(); sum[i]+=sum[i-1]; a[i]=sum[i]+i; sqr[i]=(a[i]+L+1)*(a[i]+L+1); } for(int i=1;i<=n;++i) { while(head<tail&&calc(que[head],que[head+1])<=(a[i]<<1)) ++head; f[i]=f[que[head]]+(a[i]-a[que[head]]-L-1)*(a[i]-a[que[head]]-L-1); while(head<tail&&calc(que[tail],i)<calc(que[tail-1],que[tail])) --tail; que[++tail]=i; } printf("%lld",f[n]); return 0; }