[51NOD1959]循环数组最大子段和(dp,思路)

题目链接: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\n", 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\n", max(ret1, sum+ret2));
37   }
38   return 0;
39 }

 

posted @ 2016-10-24 19:18  Kirai  阅读(184)  评论(0编辑  收藏  举报