bzoj 1911 特别行动队
Description
Input
Output
Sample Input
4
-1 10 -20
2 2 3 4
-1 10 -20
2 2 3 4
Sample Output
9
HINT
设f[i]为前i名的战斗力和的最大值
设f[i]为前i名的战斗力和的最大值
设在j断比在k断更优(j>k&&j<i)
所以f[j]+a*sum(j,i)^2+bsum(j,i)+c>f[k]+a(sum(k,i)^2+bsum(k,i)+c
F[j]-f[k]+a(sum(j,i)^2-sum(k,i)^2)+b(sum(j,i)-sum(k,i))>0;
F[j]-f[k]-2asum[i](sum[k]-sum[j])+a(sum[j]^2-sum[k]^2)+b(sum[j]-sum[k])>0
F[j]-f[k]+a(sum[j]^2-sum[k]^2)+b(sum[j]-sum[k])>2asum[i](sum[k]-sum[j])
#include<cstdio>
#include<iostream>
#define ll long long
#define MAXN 1000010
using namespace std;
int n;
long long h,t;
long long f[MAXN],sum[MAXN];
long long a,b,c;
long long q[MAXN];
long long M(long long x){return x*x;}
double getk(long long k,long long j)
{
double temp=(f[k]-f[j]+a*(M(sum[k])-M(sum[j]))+b*(sum[j]-sum[k])+0.0)/2.0/(sum[k]-sum[j])/a;
return temp;
}
int main()
{
scanf("%d%lld%lld%lld",&n,&a,&b,&c);
for(int i=1;i<=n;i++)
{
scanf("%lld",&sum[i]);
sum[i]+=sum[i-1];
}
h=t=1ll;
f[0]=0,q[1]=0;
for(int i=1;i<=n;i++)
{
while(h<t&&getk(q[h+1],q[h])<=double(sum[i]))h++;
f[i]=f[q[h]]+a*M(sum[i]-sum[q[h]])+b*(sum[i]-sum[q[h]])+c;
while(h<t&&getk(q[t],q[t-1])>getk(i,q[t])) t--;
q[++t]=i;
}
printf("%lld",f[n]);
return 0;
}