51Nod - 1050

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050

解题思路:

  It's so beautiful !

  循环数组的最大子段 [l, r] 只有两种可能:

  1、0 < l <= r <= N,这一部分就是单纯地求数组的最大子段和;

  2、0 < r < l <= N,这一部分可以这么想:既然这个循环子段最大,那么数组剩下的连续子段 [r+1,l-1] 应该就是最小子段,那么我们只要求出最小子段和,再用总和减去这个最小子段和,得到的肯定就是最大循环子段和。

AC代码:

#include <cstdio>
#include <algorithm>

using namespace std;
typedef long long ll;
const int maxn=50000+3;
ll A[maxn],dp[maxn];
int main(){
    int N;
    scanf("%d",&N);
    bool zero=true;
    for(int i=1;i<=N;i++){
        scanf("%lld",&A[i]);
        if(A[i]>=0) zero=false;
    }
    if(zero)    printf("0\n");
    else{
        dp[1]=A[1];
        ll ans=dp[1];
        for(int i=2;i<=N;i++){
            dp[i]=max(A[i],A[i]+dp[i-1]);
            if(dp[i]>ans)   ans=dp[i];
        }
        printf("%lld\n",ans);
    }

    return 0;
}

 

posted @ 2017-10-31 22:26  Blogggggg  阅读(183)  评论(0编辑  收藏  举报