输入
第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N+1行:N个整数 (-10^9 <= S[i] <= 10^9)
输出
输出循环数组的最大子段和。
输入示例
6
-2
11
-4
13
-5
-2
输出示例
20
分析:
(1)笨方法,我们可以用普通最大子段和的方法解决这个问题。我们从每个位置“断开”环,然后按普通的最大子段和的方法去做。这样做的复杂度是O(n^2)。
(2)巧妙点的方法,最优解 = max(普通的最大子段和, 总和 – 普通的“最小子段和”)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int SIZE = 50000 + 10;
int arr[SIZE], n;
ll sum = 0, dp[SIZE];
int main() {
// freopen("in.txt", "r", stdin);
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &arr[i]);
sum += arr[i];
}
ll ans = -INF;
for (int i = 1; i <= n; ++i) {
dp[i] = max(dp[i - 1] + arr[i], (ll)arr[i]);
if (ans < dp[i]) ans = dp[i];
}
for (int i = 1; i <= n; ++i) {
dp[i] = min(dp[i - 1] + arr[i], (ll)arr[i]);
if (ans < sum - dp[i]) ans = sum - dp[i];
}
printf("%lld\n", ans);
return 0;
}