BZOJ1911: [Apio2010]特别行动队

斜率优化…
首先n^2的dp很好想…
dp[i]=max{dp[j]+a*sqr(s[i]-s[j])+b*(s[i]-s[j])+c;}(0 <= j < i)
将所有只与j有关的项拎出来设为F(j)=dp[j]+sqr(s[j])-b*s[j];
将所有只与i有关的项拎出来设为一个变量all=a*sqr(s[i])+b*s[i]+c;
对于any的j,k(k < j),若j优于k意味着:
F(j)-2*a*s[i]*s[j]>F(k)-2*a*s[i]*s[k];
( F(j)-F(k) )/( s[j]-s[k] )/2/a < s[i];
经典的斜率优化形式…
优于s[i]是单调的,于是维护一个斜率递增的单调队列即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define int long long
//by:MirrorGray
using namespace std;
const int N=2111111;
int a,b,c,dp[N],q[N],s[N];

inline int sqr(int x){
    return x*x;
}

inline int F(int x){
    return dp[x]+a*s[x]*s[x]-b*s[x];
}

#undef int
int main(){
    #define int long long
    int n;scanf("%lld",&n);
    scanf("%lld%lld%lld",&a,&b,&c);
    for(int i=1;i<=n;i++){
        scanf("%lld",&s[i]);
        s[i]+=s[i-1];
    }
    int bi=0,en=0;
    q[0]=0;
    for(int i=1;i<=n;i++){
        while(bi<en&&F(q[bi+1])-F(q[bi])>s[i]*2*a*(s[q[bi+1]]-s[q[bi]]))bi++;
        dp[i]=dp[q[bi]]+a*sqr(s[i]-s[q[bi]])+b*(s[i]-s[q[bi]])+c;
        while(bi<en&&(F(i)-F(q[en]))*(s[q[en]]-s[q[en-1]])>(F(q[en])-F(q[en-1]))*(s[i]-s[q[en]]))en--;
        q[++en]=i;
    //  cout<<bi<<" "<<en<<" "<<dp[i]<<endl;
    }
    printf("%lld\n",dp[n]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值