求区间[L,R]的最大子区间
朴素做法
预处理前缀和,枚举左右端点维护答案。复杂度
优化
采用分治。将区间[L,R]分为[L,Mid]和[Mid+1,R],则最大子区间有以下三种情况:
- 完全位于左区间;
- 完全位于右区间;
- 横跨左右区间;
因此
均在之前求得,因此只需要线性时间求,即从Mid位置向前后分别扫描,维护各自的MAX,最后加和即可。复杂度
再优化
运用前缀和的思想,选择第i个数时,要再加上前面的区间[l,r],当且仅当。因此可以从头向前扫,一旦SUM为负就清零,否则就加上当前数字并维护答案。复杂度
代码3
#include<bits/stdc++.h>
using namespace std;
const int N=2E5+10;
int n,ans,sum,k=-N;
inline int read()
{
int ret=0,flag=1;char ch=getchar();
while(ch<'0' || ch>'9')
{
flag=(ch=='-')?-1:1;
ch=getchar();
}
while(ch>='0' && ch<='9')ret=ret*10+ch-'0',ch=getchar();
return ret*flag;
}
int main()
{
n=read();
for(register int i=1,tmp;i<=n;++i)
{
tmp=read();
k=max(tmp,k);
sum=(sum+tmp<=0)?0:sum+tmp;
ans=max(ans,sum);
}
cout<<(ans?ans:k)<<endl;
}