题解 P1115 最大子段和

容易想到朴素做法:

for (int l = 1; i <= n; ++i) {
    for (int r = 1; j <= n; ++j) {
        int v = s[r] - s[l - 1];
        ans = max(ans, v);
    }
}

但是显然 \(\mathrm{\color{#052242}TLE}\)

再回头看代码:想要 v 最大,只需要 \(\large{S_{l - 1}}\) 最小即可。

于是我们可以 \(O(n)\) 的动态更新 \(S_0 \sim S_{i-1}\) 最小值 \(\min_{1 \le i \le N}{S_i}\)

int m[N];
for (int i = 1; i <= n; ++i) {
    m[i] = min(m[i - 1], s[i]);
}

然后随 \(M_i\) 的更新,更新答案 \(ans = \max(S_i-M_{i-1})\) 即可。

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int a[N], m[N], s[N];
int n;

int main()
{
    ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    
    
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        cin >> a[i];
        s[i] = s[i - 1] + a[i];
        m[i] = min(m[i - 1], s[i]);
    }
    int ans = -2e4;
    for(int i = 1; i <= n; ++i)
    {
        ans = max(ans, s[i] - m[i - 1]);
    }
    cout << ans;
	return 0;
}//ACed

但是显然这份代码可以优化。

优化

1.

我们发现求完前缀和后,\(A_i\) 就没用了。

于是可以优化掉 \(A_i \to t\)

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int m[N], s[N];
int n;

int main()
{
    ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    
    
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        int t; cin >> t;
        s[i] = s[i - 1] + t;
        m[i] = min(m[i - 1], s[i]);
    }
    int ans = -2e4;
    for(int i = 1; i <= n; ++i)
    {
        ans = max(ans, s[i] - m[i - 1]);
    }
    cout << ans;
	return 0;
}//ACed

2.

两个循环都是 \(\mathrm{for\space\space i=1\sim N}\)。可以合并减小常数

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int m[N], s[N], ans = -2e4;
int n;

int main()
{
    ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    
    
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        int t; cin >> t;
        s[i] = s[i - 1] + t;
        m[i] = min(m[i - 1], s[i]);
        ans = max(ans, s[i] - m[i - 1]);
    }
    cout << ans;
	return 0;
}//ACed

3.

发现只需要用到 \(M_{i - 1}\) 于是 \(M_{i - 1} \to mi\) 且每次求完答案后更新 \(mi\) 即可。

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int mi, s[N], ans = -2e4;
int n;

int main()
{
    ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    
    
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        int t; cin >> t;
        s[i] = s[i - 1] + t;
        ans = max(ans, s[i] - mi);
        mi = min(mi, s[i]);
    }
    cout << ans;
	return 0;
}

4.

同理,只需要用到 \(S_i\),优化掉即可

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int mi, s, ans = -2e4;
int n;

int main()
{
    ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    
    cin >> n;
    for(int i = 1; i <= n; ++i) {
        int t; cin >> t;
        s += t;
        ans = max(ans, s - mi);
        mi = min(mi, s);
    }
    cout << ans;
	return 0;
}
posted @ 2024-07-22 10:16  lyfandlzf  阅读(3)  评论(0编辑  收藏  举报