【BZOJ】1911: [Apio2010]特别行动队(斜率优化dp)

题目

传送门:QWQ

 

 

分析

用$ dp[i] $ 表示前 i 个人组成的战斗力之和

然后显然$ dp[i]=Max (  dp[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c ) $

然后就是斜率优化dp的套路,设个k比j优...........

然后对最后得出的式子搞斜率优化(太长了懒得写)

 

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=1000005;
typedef long long ll;
ll dp[maxn],sum[maxn],x[maxn], a, b, c;
int que[maxn], L, R;
inline double slope(int j,int k){
    return (double)((dp[j]+a*sum[j]*sum[j]-b*sum[j]-dp[k]-a*sum[k]*sum[k]+b*sum[k]))/(double)(sum[j]-sum[k])/(double)(2*a);
}
ll sqr(ll a){return a*a;};
int main(){
    int n; 
    scanf("%d%lld%lld%lld",&n,&a,&b,&c);
    for(int i=1;i<=n;i++) scanf("%lld",&x[i]),sum[i]=sum[i-1]+x[i];
    for(int i=1;i<=n;i++){
        while(L<R && slope(que[L],que[L+1])<(double)(sum[i])) L++;
        int j=que[L];//printf("----  %d %lf %lf %lf\n",j,slope(1,2),slope(2,3),slope(3,4));
        dp[i]=dp[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+b*(sum[i]-sum[j])+c;
        while(L<R && slope(que[R-1],que[R])>slope(que[R],i)) R--;
        que[++R]=i; 
    }
    printf("%lld\n",dp[n]);
    return 0;
    
}

 

 

 

posted @ 2018-06-15 00:43  noble_(noblex)  阅读(135)  评论(0编辑  收藏  举报
/* */