洛谷P1121题解:环形数组最大两段子段和的高效解法

一、问题分析
题目要求在一个环形数组中找到两个不相交的子段,使它们的和最大。这个问题可以分解为两种情况:
线性情况:两段都在数组的同一侧
环形情况:两段跨越数组的首尾
二、算法核心思路
预处理:
计算数组总和
预处理前缀/后缀最大子段和
预处理前缀/后缀最小子段和
线性情况处理:
环形情况处理:
计算总和减去最小两段子段和
使用类似方法处理最小子段和
特殊情况处理:
处理全负数数组的情况
三、完整代码实现(带注释)
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main() {
ios::sync_with_stdio(false); // 加速输入输出
cin.tie(nullptr); // 解除cin与cout的绑定
int n;
cin >> n;
vector<int> a(n);
int total = 0;
// 读取输入并计算总和
for (int i = 0; i < n; ++i) {
cin >> a[i];
total += a[i];
}
// 情况1:线性情况(两段都在同一侧)
int max_single = INT_MIN;
vector<int> prefix_max(n), suffix_max(n);
// 从左到右计算最大子段和
int current = 0;
for (int i = 0; i < n; ++i) {
current = max(a[i], current + a[i]);
max_single = max(max_single, current);
prefix_max[i] = max_single;
}
// 从右到左计算最大子段和
max_single = INT_MIN;
current = 0;
for (int i = n-1; i >= 0; --i) {
current = max(a[i], current + a[i]);
max_single = max(max_single, current);
suffix_max[i] = max_single;
}
// 计算线性情况的最大值
int linear_max = INT_MIN;
for (int i = 0; i < n-1; ++i) {
linear_max = max(linear_max, prefix_max[i] + suffix_max[i+1]);
}
// 情况2:环形情况(总和减去最小子段和)
int min_single = INT_MAX;
vector<int> prefix_min(n), suffix_min(n);
// 从左到右计算最小子段和
current = 0;
for (int i = 0; i < n; ++i) {
current = min(a[i], current + a[i]);
min_single = min(min_single, current);
prefix_min[i] = min_single;
}
// 从右到左计算最小子段和
min_single = INT_MAX;
current = 0;
for (int i = n-1; i >= 0; --i) {
current = min(a[i], current + a[i]);
min_single = min(min_single, current);
suffix_min[i] = min_single;
}
// 计算环形情况的最大值
int circular_max = INT_MIN;
for (int i = 0; i < n-1; ++i) {
int sum = total - (prefix_min[i] + suffix_min[i+1]);
circular_max = max(circular_max, sum);
}
// 处理全负数情况
if (max(linear_max, circular_max) < 0) {
int first = INT_MIN, second = INT_MIN;
for (int num : a) {
if (num > first) {
second = first;
first = num;
} else if (num > second) {
second = num;
}
}
cout << first + second << endl;
return 0;
}
cout << max(linear_max, circular_max) << endl;
return 0;
}四、调试技巧
注意边界条件处理
测试全负数数组的特殊情况
验证环形情况的计算逻辑
检查数组越界问题
原创内容 转载请注明出处
