BNUOJ--19065 鸣人的查克拉

如果在某个时刻发动这个忍术,鸣人需要先消耗该时刻的查克拉值;在某个时候结束这个忍术,鸣人能获得该时刻的查克拉值(忍术必须先发动才能结束)。当然,如果某时刻鸣人具有的查克拉值少于该时刻的查克拉值,那么鸣人是不能发动该忍术的。
由于鸣人对这个忍术还不能很好地控制,所以他最多只能发动两次该忍术,并且两次忍术不能同时发动,也就是说必须结束一次忍术才能发动下一次(第一次结束时可以立即发动第二次)。

现在仪式已经做完了,鸣人知道了自己的查克拉的初始值,以及各个时刻的查克拉值,如果他最多可以发动两次该忍术(他也可以选择发动一次或者不发动),那么他最多能达到的查克拉值是多少?

http://www.bnuoj.com/bnuoj/problem_show.php?pid=29065

首先,先从前向后扫一遍,维护序列中的最小查克拉值,求出做最多一次忍术时每时刻的查克拉最大值f[i],不断更新ans。

载从后向前扫一遍,维护序列的最大值,算出在每时刻进行第二次忍术后的查克拉值,更新ans。

#include 
#include 
#include 
using namespace std;
const int maxn = 10000 + 10;
const int inf = 0x3f3f3f3f;
int c, n, a[maxn], f[maxn];
int main(){
    scanf("%d%d", &c, &n);
    int mi = inf, mx = -inf, ans = c, k;
    memset(f, -1, sizeof(f));
    f[0] = c;
    for(int i=1; i<=n; i++) {
        scanf("%d", &a[i]);
        if(a[i] < mi){
            mi = a[i];
            k = i;
        }
        if(max(c, f[k]) - mi >= 0)
            f[i] = max(f[i - 1], c - mi + a[i]);
        ans = max(ans, f[i]);
    }
    for(int i=n; i>0; i--){
        mx = max(mx, a[i]);
        if(f[i] >= a[i])       //名人在做一次忍术的情况下,在i时刻最多拥有f[i]查克拉。即当前可以消耗的查克拉值最多是f[i]。
            ans = max(ans, f[i] - a[i] + mx);
    }
    printf("%d\n", ans);
    return 0;
}


你可能感兴趣的:(bnuoj)