题目大意:给出一组数字序列,要你求出两段子数组和两者相加的最大值
解题思路:求出1~i的序列的子数组和的最大值,i~n的序列的子数组和的最大值
然后枚举k, 1<=k<=n-1;求1~k的子数组和的最大值与k+1~n的子数组和的最大值相加所得到的最大数.
关于求数组连续的子数组最大和,《编程之美》上有O(n)的求法。
求法如下:
考虑元素a[k], 以及最大的一段数组a[i]~~a[j]
1.当k = i = j时,元素a[k]本身构成了和的最大一段。
2.当k=i<j时,元素a[k]和最大一段数组构成了最大段。
3.当k < i时,元素a[k]和后面的最大段没关系
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <climits>
using namespace std;
const int maxn = 50010;
int a[maxn], t, lr[maxn], rr[maxn];
int main()
{
scanf("%d", &t);
while(t-- != 0)
{
int n, ls, rs;
int ans = INT_MIN;
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
rs = a[n - 1];
rr[n - 1] = a[n - 1];
for(int i = n - 2; i >= 0; i--)
{
rs = max(a[i], a[i] + rs);
rr[i] = max(rs, rr[i + 1]);
}
ls = a[0];
lr[0] = a[0];
for(int i = 1; i < n; i++)
{
ls = max(a[i], a[i] + ls);//比较上述情况1,2两者的大小
lr[i] = max(ls, lr[i - 1]);//比较上述情况3与1,2的大小
}
for(int k = 0; k < n - 1; k++)
ans = max(ans, lr[k] + rr[k+1]);
printf("%d\n", ans);
}
return 0;
}