题目链接:http://218.28.220.249:50015/JudgeOnline/problem.php?id=1282
水题一道
题意:给定一个长度为50000的数组,求它的循环数组的最大子段和。
分析:本题与普通的最大子段和问题不同的是,最大子段和可以是首尾相接的情况,即可以循环。那么这个题目的最大子段和有两种情况 (1)正常数组中间的某一段和最大。这个可以通过普通的最大子段和问题求出。 (2)此数组首尾相接的某一段和最大。这种情况是由于数组中间某段和为负值,且绝对值很大导致的,那么我 们只需要把中间的和为负值且绝对值最大的这一段序列求出,用总的和减去它就行了。 即,先对原数组求最大子段和,得到ans1,然后把数组中所有元素符号取反,再求最大子段和,得到ans2, 原数组的所有元素和为ans,那么最终答案就是 max(ans1, ans + ans2)。
代码:
#include<iostream> using namespace std; typedef long long LL; LL arr[50003]; int main() { LL ans;//1~n总和 LL ans1;//普通的子列和 LL ans2;//(成环时)子列为负数时的和 LL n; while(cin>>n) { ans=ans1=ans2=0; LL MAX=0;//普通的子列最大和 LL MIN=0;//(成环时)子列为负数且绝对值最大时的和 for(LL i=0;i<n;i++) { cin>>arr[i]; ans+=arr[i]; } for(LL i=0;i<n;i++) { ans1+=arr[i]; ans2+=arr[i]; MAX=max(MAX,ans1); MIN=min(MIN,ans2); if(ans1<0) ans1=0; if(ans2>0) ans2=0; } cout<<max(ans-MIN,MAX)<<endl; } return 0; }