[bzoj 3156]防御准备

124 篇文章 2 订阅
26 篇文章 0 订阅

这里写图片描述
这道题一看就是dp,不过数据范围让我们不能O(n^2),所以就要优化。dp方程为f[i]=min(f[j]+(i-j)*(i-j-1)/2+a[i]),这种形式便想到了斜率优化。
设i>j>k,j比k优
f[j]+(i-j)* (i-j-1)/2+a[i]< f[k]+(i-k)* (i-k-1)/2+a[i]
化得
[(f[j]+j* (j+1)/2)-(f[k]+k* (k+1)/2)]/(j-k)< i
设Y[i]=f[i]+i*(i+1)/2,X[i]=i
(Y[j]-Y[k])/(X[j]-X[k])< i
化为斜率形式后,就可以做了。(大坑点:全部要long long)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
long long f[1100000],a[1100000],v[11000000];
long long YY(long long x){return f[x]+x*(x+1)/2;}
long long Y(long long x,long long y){return YY(y)-YY(x);}
long long X(long long x,long long y){return y-x;}
int main()
{
    long long n;
    scanf("%lld",&n);
    for(long long i=1;i<=n;i++)scanf("%lld",&a[i]);
    long long head=1,tail=1;
    for(long long i=1;i<=n;i++)
    {
        while(head<tail && Y(v[head],v[head+1])<i*X(v[head],v[head+1]))head++;
        long long x=v[head];
        f[i]=f[x]+(i-x)*(i-x-1)/2+a[i];
        while(head<tail && Y(v[tail-1],v[tail])*X(v[tail],i)>Y(v[tail],i)*X(v[tail-1],v[tail]))tail--;
        v[++tail]=i;
    }
    printf("%lld\n",f[n]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值