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

时间:2021-10-29 18:34:25

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

这道题的最大子段和有两种可能,一种是常规的子段和,另一种是从结尾到开头的一个子段。常规做是一种可能,另一种带循环的则可以认为是序列中间有一段最小子段和,把这段最小子段和去掉,剩下的可能就是最大子段和了。

 #include <bits/stdc++.h>
using namespace std; typedef long long LL;
const int maxn = * ;
int n;
int a[maxn]; int main() {
// freopen("in", "r", stdin);
while(~scanf("%d", &n)) {
bool flag = ;
LL sum = , ret1 = , ret2 = ;
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
sum += a[i];
if(a[i] < ) flag = ;
}
if(!flag) {
printf("%lld\n", sum);
continue;
}
LL tmp = ;
for(int i = ; i <= n; i++) {
ret1 = max(tmp, ret1);
tmp += a[i];
if(tmp < ) tmp = ;
}
for(int i = ; i <= n; i++) a[i] = -a[i];
tmp = ;
for(int i = ; i <= n; i++) {
ret2 = max(tmp, ret2);
tmp += a[i];
if(tmp < ) tmp = ;
}
printf("%lld\n", max(ret1, sum+ret2));
}
return ;
}