51Nod - 1050

N个整数组成的循环序列a 11,a22,a33,…,ann,求该序列如aii+ai+1i+1+…+ajj的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑an1n−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;
}

  

猜你喜欢

转载自www.cnblogs.com/clb123/p/12328038.html