最大子段和 - 题解
最大子段和
时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 128MB,其他语言 256MB描述
给出一个长度为 \(n\) 的序列 \(a\),选出其中连续且非空的一段使得这段和最大。
输入描述
第一行是一个整数,表示序列的长度 \(n\)。
第二行有 \(n\) 个整数,第 \(i\) 个整数表示序列的第 \(i\) 个数字 \(a_i\)
\(1≤n≤2×10^5\),\(−10^4≤a_i≤10^4\)。输出描述
输出一行一个整数表示答案。
用例输入 1
7 2 -4 3 -1 2 -4 3
用例输出 1
4
提示
【样例解释】
选取 \([3,5]\) 子段 \(3,−1,2\), 其和为 \(4\)
代码
贪心 做法
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
int x=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^'0');
ch=getchar();
}
return x*w;
}
const int N=2e5+5,INF=0x3f3f3f3f;
int n,a[N],f[N];
int main()
{
n=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=n;i++)
f[i]=max(a[i],f[i-1]+a[i]);
int ans=-INF;
for(int i=1;i<=n;i++)
ans=max(ans,f[i]);
printf("%d\n",ans);
return 0;
}
类线段树 做法
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
int x=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^'0');
ch=getchar();
}
return x*w;
}
const int N=2e5+5;
int n,a[N];
struct RANGE{
int l,r;
int sum;
int dat,ldat,rdat;
void build(int il,int ir,int isumdat)
{
l=il,r=ir, sum=dat=ldat=rdat=isumdat;
return;
}
void build(int il,int ir,int isum,int idat,int ildat,int irdat)
{
l=il,r=ir, sum=isum, dat=idat,ldat=ildat,rdat=irdat;
return;
}
};
RANGE rg[N<<2];
void div_conq(int p,int l,int r)
{
if(l==r)
{
rg[p].build(l,r,a[l]);
return;
}
int mid=(l+r)>>1;
div_conq(p<<1,l,mid), div_conq((p<<1)+1,mid+1,r);
rg[p].build(
l,r,
rg[p<<1].sum+rg[(p<<1)+1].sum,
max(
max(
rg[p<<1].dat,
rg[(p<<1)+1].dat
),
rg[p<<1].rdat+rg[(p<<1)+1].ldat
),
max(
rg[p<<1].ldat,
rg[p<<1].sum+rg[(p<<1)+1].ldat
),
max(
rg[(p<<1)+1].rdat,
rg[p<<1].rdat+rg[(p<<1)+1].sum
)
);
return;
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
a[i]=read();
div_conq(1,1,n);
printf("%d\n",rg[1].dat);
return 0;
}
本文采用 「CC-BY-NC 4.0」 创作共享协议,转载请注明作者及出处,禁止商业使用。
作者:Jerrycyx,原文链接:https://www.cnblogs.com/jerrycyx/p/18331293