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;
}
原文地址:https://www.cnblogs.com/lovewhy/p/9633710.html