题面
给你一串数,从里面任意挑出一串连续排列的数(一个区间),求所有区间数的加和的最大值。
思考
首先是无脑暴力,直接套i,j,k三个循环,遍历所有可能性即可。但是这样很明显,O(n3)的时间复杂度会让一些较大的数据TLE。所以再思考……
接着是前缀和做法,开一个sum数组记录当前位置以及前面所有数的加和,可以省掉for(int k=i;k<=j;k++)的循环,但是O(n2)还是不够满意。所以再思考……
接着是想,符合条件的区间会满足怎么样的特性呢?首先是,满足条件的区间(和最大的那个),左右两端(不在区间内)的数,要么是超过数组范围,要么就是负数/0。因为如果是正数的话,很明显可以加入这个正数进入区间当中,区间和又会增加(反证法),证明了第一个特性
我们再想,如果满足条件的区间,是不是没在满足条件区间之内的线段(和满足条件区间相邻的),和一定是负数/0,证明同上面一致。
所以结论出现了,如果我们当前扫到的区间和为负数,那么它一定不在满足条件的区间之内,直接舍掉就好,代码如下
代码
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 10000
int a[maxn];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int sum=0;
int maxm=0;
for(int i=0;i<n;i++)
{
maxm=max(sum,maxm);
if(sum<0)
sum=0;
sum+=a[i];
}
cout<<maxm<<endl;
}
/*
8
-1 3 -2 4 -6 1 6 -1
*/