【BZOJ 1911】 [Apio2010]特别行动队

【链接】 我是链接,点我呀:)
【题意】

在这里输入题意

【题解】

设f[i]表示把第i个士兵放在最后一段的最后一个的最大值。 s[i] = x[1] + x[2]+..+x[i]; 则有 $f[i] = max(f[j] + a*{s[i]-s[j]}^2+b*(s[i]-s[j])+c)$ 斜率优化。 最后输出f[n]即可

【错的次数】

在这里输入错的次数

【反思】

在这里输入反思

【代码】

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 1e6;

int n,dl[N+10],h,t;
ll f[N+10],s[N+10],a,b,c;

ll sqr(ll x)
{
    return x*x;
}

double ju(int x,int y)
{
    double fenzi = f[y] + a*sqr(s[y]) - b*s[y]-(f[x]+a*sqr(s[x])-b*s[x]);
    double fenmu = 2*a*(s[y]-s[x]);
    return fenzi/fenmu;
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);

    scanf("%d",&n);
    scanf("%lld%lld%lld",&a,&b,&c);
    for (int i = 1;i <= n;i++)
    {
        ll x;
        scanf("%lld",&x);
        s[i] = s[i-1] + x;
    }

    h = t = 1;
    dl[1] = 0;
    for (int i = 1;i <= n;i++)
    {
        while (h < t && ju(dl[h],dl[h+1]) < s[i]) h++;
        int j = dl[h];
        f[i] = f[j] + a*sqr(s[i]-s[j])+b*(s[i]-s[j])+c;
        while (h < t && ju(dl[t-1],dl[t]) > ju(dl[t],i)) t--;
        dl[++t] = i;
    }
    printf("%lld\n",f[n]);
    return 0;
}

posted @ 2017-10-10 09:37  AWCXV  阅读(98)  评论(0编辑  收藏  举报