题目链接: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 "); 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 ",ans); } return 0; }