把限长子段和写成前缀和之差,用单调队列维护最近 m 个前缀和的最小值。
OJ: luogu
题目 ID: P1714
难度:普及/提高-
标签:前缀和单调队列python
日期: 2025-12-26 19:34
题意
选择长度在
思路
设 prefix[i] 为前 i 时,合法左端前缀 j 位于 [i-m,i-1],子段和是 prefix[i]-prefix[j]。因此只需维护这个滑动窗口内最小的前缀和。
递增单调队列保存候选前缀;先删除过期队头并计算答案,再把当前前缀作为未来候选加入。
Python 知识
- 不保存完整前缀数组,只用变量
prefix在线累加。 - 两个紧凑数组分别保存候选下标与前缀值,适合五十万规模。
- 流式整数解析同时支持负数并控制内存。
代码
python
import os
from array import array
def read_ints():
number = 0
sign = 1
reading = False
while chunk := os.read(0, 1 << 20):
for byte in chunk:
if 48 <= byte <= 57:
number = number * 10 + byte - 48
reading = True
else:
if reading:
yield sign * number
number = 0
sign = 1
reading = False
elif byte == 45:
sign = -1
if reading:
yield sign * number
data = iter(read_ints())
n, limit = next(data), next(data)
queue_index = array("i", [0]) * (n + 1)
queue_value = array("q", [0]) * (n + 1)
head, tail = 0, 1
prefix = 0
answer = -10**30
for i in range(1, n + 1):
prefix += next(data)
while head < tail and queue_index[head] < i - limit:
head += 1
answer = max(answer, prefix - queue_value[head])
while head < tail and queue_value[tail - 1] >= prefix:
tail -= 1
queue_index[tail] = i
queue_value[tail] = prefix
tail += 1
print(answer)复杂度
时间复杂度
总结
限长最大子段和等价于“当前前缀减最近窗口内最小前缀”。