【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;
}