循环数组的最大子段和
问题描述:
N个整数组成循环序列,求这个序列的最大子段和。
例如:-2 11 -4 13 -5 -2 ANSWER: 20
解决:
解决这个问题需要有求解最大子段和的基础。
循环数组的最大子段和有两种情况: 一种是普通情况,另一种就是跨越一部分头和尾的情况。
对于第二种情况,如果拥有最大和的子段跨越了头和尾,那这时,中间的那一段就是一个 “最小子段和” ,因为序列的总和是一定的。
那么,怎么知道这个最小子段在哪里呢,我们只要把所有的数都取负,再求一次最大子段和就可以了。
那么也就是说,循环数组的最大子段和,就是求了两次最大子段和。
#include<cstdio> #include<algorithm> #include<cstring> #define ll long long using namespace std; ll a[50005],b[50005]; ll mxsub(ll a[],int n) { ll sum=-999999999,b=0; for(int i=0;i<n;i++) { if(b>0) b+=a[i]; else b=a[i]; if(b>sum) sum=b; } return sum; } int main() { int n; while(scanf("%d",&n)!=EOF) { ll s=0; for(int i=0;i<n;i++) { scanf("%lld",&a[i]); //输入序列 s+=a[i]; // 求整个序列的和 b[i] = -a[i]; // 把整个序列取负放在另一个序列里 } ll ans=mxsub(a,n); // 普通情况下的最大子段和 ll ans2=s + mxsub(b,n); // 跨越头和尾的 ans = max(ans,ans2); // 两者取大 printf("%lld\n",ans); } return 0; }
如果有什么不对的地方,还请各位大神批评指正~