最大子段和
题目描述
给出一个长度为 的序列 ,选出其中连续且非空的一段使得这段和最大。
输入格式
第一行是一个整数,表示序列的长度 。
第二行有 个整数,第 个整数表示序列的第 个数字 。
输出格式
输出一行一个整数表示答案。
样例 #1
样例输入 #1
7
2 -4 3 -1 2 -4 3
样例输出 #1
4
提示
样例 1 解释
选取 子段 ,其和为 。
数据规模与约定
- 对于 的数据,保证 。
- 对于 的数据,保证 ,。
思路
用divide函数找出数组中给定范围(l到r)内的最大子段和。如果l等于r,即范围内只有一个元素,那么最大子段和就是这个元素本身,直接返回这个元素。
如果范围内有多个元素,那么就需要使用分治策略。首先,找出范围的中点mid,然后将原问题分解为两个子问题:找出左半部分(l到mid)的最大子段和,以及右半部分(mid+1到r)的最大子段和。这两个子问题可以通过递归调用divide函数来解决。
然后,需要考虑跨越中点的子段和。从中点向左右两侧分别开始,累加元素值,并在过程中保留最大的累加和。
最后,返回这三个值(左半部分的最大子段和,右半部分的最大子段和,跨越中点的最大子段和)中的最大值,即为给定范围内的最大子段和。
AC代码
#include <algorithm>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
const int N = 1e7 + 7;
int n;
int a[N];
int divide(int l, int r) {
if (l == r) {
return a[l];
}
int mid = (l + r) >> 1;
int sum1, sum2;
int max1, max2;
sum1 = sum2 = 0;
max1 = max2 = -0x3f3f3f3f;
for (int i = mid; i >= l; i--) {
sum1 += a[i];
max1 = max(max1, sum1);
}
for (int i = mid + 1; i <= r; i++) {
sum2 += a[i];
max2 = max(max2, sum2);
}
return max(max(divide(l, mid), divide(mid + 1, r)), max1 + max2);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
cout << divide(1, n) << endl;
return 0;
}