洛谷 P1115 最大子段和 题解

原题链接点这里

题目描述

给出一个长度为 $n$ 的序列 $a$,选出其中连续且非空的一段使得这段和最大。

输入格式

第一行是一个整数,表示序列的长度 $n$。

第二行有 $n$ 个整数,第 $i$ 个整数表示序列的第 $i$ 个数字 $a_i$。

输出格式

输出一行一个整数表示答案。

样例 #1

样例输入 #1

7
2 -4 3 -1 2 -4 3

样例输出 #1

4

提示

样例 1 解释

选取 $[3, 5]$ 子段 ${3, -1, 2}$,其和为 $4$。

数据规模与约定

  • 对于 $40\%$ 的数据,保证 $n \leq 2 \times 10^3$。
  • 对于 $100\%$ 的数据,保证 $1 \leq n \leq 2 \times 10^5$,$-10^4 \leq a_i \leq 10^4$。

介绍

这里可以用dp解决。状态也是第i个选不选,f[i]代表的是以i为结尾前面的最大子序列是多少,f[i] = max(f[i - 1] + a[i], a[i])如果前面i-1的再加上a[i]还比a[i]小,那么就选这个a[i],然后res更新一下。

源码

#include <bits/stdc++.h>

using namespace std;

#define LL long long

#define endl "\n"

const int N = 2e5 + 10;

const int M = 110;

int n;
int a[N],f[N];

void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> a[i];

    int res = -0x3f3f3f3f;
    for (int i = 1; i <= n; i ++ )
    {
        f[i] = max(f[i - 1] + a[i], a[i]);

        res = max(res, f[i]);
    }
    cout << res << endl;

}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    solve();

    return 0;
}
THE END