51Nod - 1050
N个整数组成的循环序列a11,a22,a33,…,ann,求该序列如aii+ai+1i+1+…+ajj的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑an−1n−1,ann,a11,a22这样的序列)。当所给的整数均为负数时和为0。
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
Input第1行:整数序列的长度N(2 <= N <= 50000) 第2 - N+1行:N个整数 (-10^9 <= Sii <= 10^9)Output输出循环数组的最大子段和。Sample Input
6 -2 11 -4 13 -5 -2
Sample Output
20

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
ll a[N],dp1[N],dp2[N];
int main()
{
ll n;
memset(a,0,sizeof(a));
cin>>n;
ll sum = 0;
for(int i = 0; i < n; i++) {
cin>>a[i];
sum += a[i];
}
ll ans = 0;
ll max1 = -N;
ll max2 = -N;
ll x1,x2;
for(int i = 0; i < n; i++) {
dp1[i] = max(dp1[i-1]+a[i],a[i]);//求最大子段和
if(max1 < dp1[i]) {
max1 = dp1[i];
x1 = i;
}
}
for(int i = 0; i < n; i++) {
a[i] = -a[i];
}
for(int i = 0; i < n; i++) {
dp2[i] = max(dp2[i-1]+a[i],a[i]);//取负后求最大子段和
if(max2 < dp2[i]) {
max2 = dp2[i];
x2 = i;
}
}
ll min = -dp2[x2];//求最小子段和
if(dp1[x1] > sum - min) {//比较两种情况求的子段和的大小,取大的
cout<<dp1[x1]<<endl;
}
else {
cout<<sum-min<<endl;
}
return 0;
}

浙公网安备 33010602011771号