bzoj 1911 [Apio2010]特别行动队斜率优化+DP

                                        bzoj 1911 特别行动队

Description

Input

Output

Sample Input

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;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值