最大连续和——单调队列
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;
}

浙公网安备 33010602011771号