[bzoj3156] 防御准备 DP斜率优化

3156: 防御准备

Description

这里写图片描述

Input

第一行为一个整数N表示战线的总长度。

第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。

Output

共一个整数,表示最小的战线花费值。

Sample Input

10

2 3 1 5 4 5 6 3 1 2

dp[i]=dp[j]+a[i]+(i-j)*(i-j-1)/2;
如果j比k优
dp[j]+(i-j)(i-j-1)/2 < dp[k]+(i-k)*(i-k-1)/2;
dp[j]-dp[k]+(j*j+j)/2 - (k*k+k)/2 < i*(j-k);

注意要用long long

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N = 1000000 + 5;
ll f[N],cost[N],q[N];
int n,head=1,tail=1;
double xie( ll j, ll k ){ return (2.0*(f[j]-f[k])+j*(j+1)-k*(k+1))/(2.0*j-2.0*k);}
int main(){
    scanf("%d", &n);
    for( int i = 1; i <= n; i++ ) scanf("%lld", &cost[i]);
    for( int i = 1; i <= n/2; i++ ) swap( cost[i], cost[n-i+1] );
    f[1] = cost[1]; ll ans = cost[1] + 1ll*n*(n-1)/2ll; q[1] = 1;
    for( int i = 2; i <= n; i++ ) {
        while( head < tail && xie( q[head+1], q[head] ) < i ) head++;
        f[i] = f[q[head]] + 1ll*(i-q[head])*(i-q[head]-1)/2 + cost[i];
        ans = min( ans, f[i] + 1ll*(n-i+1)*(n-i)/2 );
        while( head < tail && xie( q[tail], q[tail-1] ) > xie( i, q[tail] )) tail--;
        q[++tail] = i;
    }
    printf("%lld", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值