前缀最大子段和(Kadane 滚动值)+ 分数的前缀最大值 g,一遍 O(n) 扫描求所有人的分数最大值,按符号取模输出。
OJ: roj
题目 ID: 3606
难度:普及-
标签:最大子段和Kadane递推前缀最大值python
创建: 2026-10-02 10:18
更新: 2026-10-06 15:07
题目描述
有
数据范围:
思路
特征值是前缀最大子段和,用 Kadane 滚动 end_here 并维护历史最大 trait。分数需要前面所有人 score+trait 的最大值,再用一个滚动变量 g 维护。全程四个标量,
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 10:18
# update_at: 2026-10-02 10:18
import sys
NEG = -(1 << 62) # 分数下界的哨兵:|分数| 不可能超过 n·2·10^9
def solve() -> None:
data = iter(sys.stdin.buffer.read().split())
n = int(next(data))
p = int(next(data))
best = NEG # 全体小朋友分数的最大值(带符号)
end_here = 0 # 以当前人结尾的最大子段和(Kadane 滚动值)
trait = NEG # 特征值:前缀 [1..i] 内的最大子段和
g = NEG # 已看过的人中 score_j + trait_j 的最大值
for i in range(n):
a = int(next(data))
end_here = max(end_here + a, a)
trait = max(trait, end_here) # 特征值不要求子段以 i 结尾
# 分数:第 1 个人是自己的特征值;
# 其他人是前面所有人中「分数 + 特征值」的最大值
score = trait if i == 0 else g
best = max(best, score)
g = max(g, score + trait)
# 输出保持符号:负数输出 -(|best| mod p),非负输出 best mod p
print(best % p if best >= 0 else -(abs(best) % p))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-06 15:06
* update_at: 2026-10-06 15:06
*/
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll NEG = -(1LL << 62); // 足够小的哨兵
ll n, p;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> p;
ll best = NEG; // 所有分数的最大值(带符号)
ll end_here = 0; // 以当前位置结尾的最大子段和
ll trait = NEG; // 特征值:前缀 [1..i] 的最大子段和
ll g = NEG; // 已处理的人中 score_j + trait_j 的最大值
for (ll i = 0; i < n; ++i) {
ll a;
cin >> a;
end_here = max(end_here + a, a);
trait = max(trait, end_here); // 特征值不要求子段以 i 结尾
ll score = trait;
if (i > 0) score = g; // 第 1 个人特征值,其余取前面 score+trait 的最大值
best = max(best, score);
g = max(g, score + trait);
}
if (best >= 0)
cout << (best % p) << "\n";
else
cout << -(abs(best) % p) << "\n";
return 0;
}