#dDDLDPybttg050502. 1598:【 例 2】最大连续和

1598:【 例 2】最大连续和

好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:


题目描述

给你一个长度为 nn 的整数序列 {A1,A2,,An}\{A_1, A_2, \dots, A_n\},要求从中找出一段 连续的长度不超过 mm 的子序列,使得这个序列的和最大。


输入格式

第一行为两个整数 n,mn, m

第二行为 nn 个用空格分开的整数,表示 A1,A2,,AnA_1, A_2, \dots, A_n,每个数的绝对值都小于 10001000


输出格式

仅一个整数,表示连续长度不超过 mm 的最大子序列和。


样例

样例输入

6 4
1 -3 5 1 -2 3

样例输出

7

样例解释

数组:[1,3,5,1,2,3][1, -3, 5, 1, -2, 3]m=4m=4

需要找长度不超过 44 的连续子序列,使和最大。

考虑所有长度不超过 44 的连续子序列:

  • 长度 1:最大为 55(子序列 [5][5]
  • 长度 2:[5,1][5,1] 和为 66
  • 长度 3:[5,1,2][5,1,-2] 和为 44
  • 长度 4:[5,1,2,3][5,1,-2,3] 和为 77

因此最大和为 77,对应子序列 [5,1,2,3][5,1,-2,3](长度 44)。


数据范围

  • 对于 50%50\% 的数据,1N,M1041 \le N,M \le 10^4
  • 对于 100%100\% 的数据,1N,M2×1051 \le N,M \le 2\times 10^5

时空限制

  • 时间:1000 ms1000 \text{ ms}
  • 内存:524288 KB524288 \text{ KB}

提示
此题为 最大子段和 的变种,增加了长度不超过 mm 的限制。

方法
Si=A1+A2++AiS_i = A_1 + A_2 + \dots + A_i(前缀和)。
则子段 [j+1,i][j+1, i] 的和为 SiSjS_i - S_j,要求 ijmi - j \le m,即 jimj \ge i - m

问题转化为:对于每个 ii,求 Siminj[im,i1]SjS_i - \min_{j \in [i-m, i-1]} S_j 的最大值,其中 j0j \ge 0(若 j=0j=0 表示取前缀和 S0=0S_0=0)。

因此可以用 单调队列 维护区间 [im,i1][i-m, i-1]SjS_j 的最小值。

步骤

  1. 计算前缀和 S[0n]S[0 \dots n]S[0]=0S[0]=0
  2. 维护一个单调递增队列(队首存储最小的 SjS_j 对应的下标);
  3. 遍历 ii11nn
    • 如果队首下标 qfront<imq_{\text{front}} < i - m,则弹出队首(因为超出窗口范围);
    • SiS[qfront]S_i - S[q_{\text{front}}] 更新答案;
    • 从队尾弹出所有 S[qback]SiS[q_{\text{back}}] \ge S_i 的下标(因为 SiS_i 更小且更靠后,比它们更优);
    • ii 入队。

注意:初始化时,先将 S0=0S_0=0 的下标 00 入队,然后从 i=1i=1 开始遍历。

复杂度:O(n)O(n)

示例(样例):

  • S=[0,1,2,3,4,2,5]S=[0, 1, -2, 3, 4, 2, 5]
  • m=4m=4
  • 单调队列维护最小前缀和,遍历得到最大差值 77