### bzoj1010: [HNOI2008]玩具裝箱toy

dp[i]=min(dp[j]+(sum[i]-sum[j]+i-j-1-L)^2)(j<i)

dp[i]=min(dp[j]+(f[i]-f[j]-c)^2)

1.證明決策單調性

f[k]>=f[j]（顯然）

2.求斜率方程

dp[k]-2*f[i]*(f[k]+c)+(f[k]+c)^2<=dp[j]-2*f[i]*(f[j]+c)+(f[j]+c)^2

(dp[k]+(f[k]+c)^2-dp[j]-(f[j]+c)^2)/2*(f[k]-f[j])<=f[i]

f[i]是單調遞增的，我們使用隊列維護一個下凸殼，每次取出隊頭作為決策

`/**************************************************************    Problem: 1010    User: zhouyuyang    Language: C++    Result: Accepted    Time:160 ms    Memory:2464 kb****************************************************************/ #include<cstdio>#include<iostream>#include<algorithm>#define ll long long using namespace std;ll a[50005],f[50005],q[50005],n,c,l,r;ll read(ll &x){    x=0;    char ch=getchar();    while (ch<'0'||ch>'9') ch=getchar();    while (ch>='0'&&ch<='9'){        x=x*10+ch-'0';        ch=getchar();    }}ll sqr(ll x){    return x*x;}double get(ll j,ll k){    return (f[k]-f[j]+sqr(a[k]+c)-sqr(a[j]+c))/(2.0*(a[k]-a[j]));}int main(){    read(n);    read(c);    c++;    for (int i=1;i<=n;i++) read(a[i]);    for (int i=1;i<=n;i++) a[i]=a[i-1]+a[i]+1;    l=1;    r=1;    q[1]=0;    for (int i=1;i<=n;i++){        while (l<r&&get(q[l],q[l+1])<=a[i]) l++;        f[i]=f[q[l]]+sqr(a[i]-a[q[l]]-c);        while (l<r&&get(q[r],i)<get(q[r-1],q[r])) r--;        r++;        q[r]=i;    }    printf("%lld",f[n]);    return 0;}`