最大连续和——单调队列

Description

给你一个长度为 n 的整数序列 A,要求从中找出一段连续的长度不超过 m 的非空子序列,使得这个序列的和最大。

input Format
第一行为两个整数 n,m;

第二行为 n 个用空格分开的整数序列,每个数的绝对值都小于 1000。

输出格式

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

Sample
样例输入
6 4
1 -3 5 1 -2 3
样例输出
7

首先不难想到算区间和需要统计前缀和,通过求sum[i]-sum[j]求出区间和,那我们现在就考虑让它最大且长度不超过m.

枚举序列,当前sum[i]一定,让和最大即让sum[j]尽可能小且长度不超过m,很符合单调队列支持的操作.

AC code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200010;
int  s[N], a[N], q[N];
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch-'0');ch=getchar();}return x*f;}inline void write(int x){if(x<0)x*=-1,putchar('-');if(x>9)write(x/10);putchar(x%10+'0');return;}inline int max(int x,int y){return (x<y)?y:x;}inline int min(int x,int y){return (x<y)?x:y;}
signed main()
{
	int n, m;
	n=read(),m=read();
	for (int i = 1; i <= n; i++)
	{
		a[i]=read();
		s[i] = s[i - 1] + a[i];
	}
	int  maxn = -1e9;
	int head = 0, tail = 0;
	for (int i = 1; i <= n; i++)
	{
		while (head <= tail && q[head] + m < i)head++;
		maxn = max(maxn, s[i] - s[q[head]]);
		while (head <= tail && s[q[tail]] >= s[i])tail--;
		q[++tail] = i;
	}
	write(maxn);
	return 0;
}
posted @ 2025-04-14 09:58  Crab2016  阅读(35)  评论(0)    收藏  举报