题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050
这道题的最大子段和有两种可能,一种是常规的子段和,另一种是从结尾到开头的一个子段。常规做是一种可能,另一种带循环的则可以认为是序列中间有一段最小子段和,把这段最小子段和去掉,剩下的可能就是最大子段和了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 50050 * 2; 6 int n; 7 int a[maxn]; 8 9 int main() { 10 // freopen("in", "r", stdin); 11 while(~scanf("%d", &n)) { 12 bool flag = 0; 13 LL sum = 0, ret1 = 0, ret2 = 0; 14 for(int i = 1; i <= n; i++) { 15 scanf("%d", &a[i]); 16 sum += a[i]; 17 if(a[i] < 0) flag = 1; 18 } 19 if(!flag) { 20 printf("%lld ", sum); 21 continue; 22 } 23 LL tmp = 0; 24 for(int i = 1; i <= n; i++) { 25 ret1 = max(tmp, ret1); 26 tmp += a[i]; 27 if(tmp < 0) tmp = 0; 28 } 29 for(int i = 1; i <= n; i++) a[i] = -a[i]; 30 tmp = 0; 31 for(int i = 1; i <= n; i++) { 32 ret2 = max(tmp, ret2); 33 tmp += a[i]; 34 if(tmp < 0) tmp = 0; 35 } 36 printf("%lld ", max(ret1, sum+ret2)); 37 } 38 return 0; 39 }