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

来源:互联网 发布:淘宝收藏 猪八戒网 编辑:程序博客网 时间:2024/04/30 19:01

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;}
0 0
原创粉丝点击