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; }