题目
题意:给出一个长度为
n
n
n 的序列
a
a
a,选出其中连续且非空的一段使得这段和最大。
输入格式:
第一行输入
n
n
n,表示序列长度为
n
n
n。
第二行有
n
n
n 个整数,第
i
i
i 个整数表示序列的第
i
i
i 个数字
a
i
a_i
ai 。
输出格式:
一行输出得到的最大子段和
思路
我们可以想到一直到第 i i i个元素的最大值为 f [ i ] = m a x ( f [ i − 1 ] + n u m [ i ] , n u m [ i ] ) f[i] = max(f[i-1]+num[i],num[i]) f[i]=max(f[i−1]+num[i],num[i]),因为如果前 i − 1 i-1 i−1段序列加上第 i i i个数还小于加入的第 i i i个数的话,那么我们必然会舍去前 i − 1 i-1 i−1个数,而保留第 i i i个数,作为接下来的子段和的一部分。
代码
核心代码
f[i] = max(f[i-1]+num[i],num[i]);
完整代码
我们不能输出
f
[
n
]
f[n]
f[n]作为答案,因为如果
n
u
m
[
i
]
num[i]
num[i]为负数的话,可能会使
f
[
i
f[i
f[i]也为负数,但如果这个时候
n
u
m
[
i
+
1
]
num[i+1]
num[i+1]为正数,那么得到的
f
[
i
+
1
]
=
n
u
m
[
i
+
1
]
f[i+1] = num[i+1]
f[i+1]=num[i+1],但是
f
[
i
+
1
]
f[i+1]
f[i+1]可能小于
f
[
i
−
1
]
f[i-1]
f[i−1],比如233 233 -666 1 1
,如果输出
f
[
n
]
f[n]
f[n]作为答案为
2
2
2,但是正确答案应为
466
466
466,所以我们还需要定义一个
s
u
m
sum
sum来表示最终得到的最大子段和
#include <bits/stdc++.h>
#include <algorithm>
#include <stack>
#define mem(s, i) memset(s, i, sizeof(s))
#define INF 0x3f3f3f3f;
#define ll long long
using namespace std;
const int N = 2e5+5;
int num[N];
void solve()
{
int n;
scanf("%d",&n);
int ans = 0;
int sum = -9999;
for(int i = 1;i <= n;i++){
scanf("%d",&num[i]);
ans = max(ans+num[i],num[i]);
sum = max(sum,ans);
}
printf("%d",sum);
}
int main()
{
ios::sync_with_stdio(false);
solve();
return 0;
}