很久以前不求甚解的看了一下,然后就没有管了,今天牛客的多校又考到这个点了,遗憾由于根本没有理解单调队列所以没有往这个方向想。
单调队列是一个双端队列,他从头到尾,首先维护了下标的递增,其次根据需要维护了值的递增或递减。
比较经典的就是滑动窗口了。
给定一个大小为k的框,可以框住k个连续的数字,现在问你框不超过k个连续数字使得这些元素和最大。
预处理前缀和sum[],那么我们应该使得区间左端点尽量靠前,且前缀和较小,右端点尽量靠后,且前缀和较大。
于是单调队列就维护了一个下标递增,且s也递增的东西。
对于i=1->n
首先将队头超出位置的元素弹出。
然后判断答案
接下来将队尾比sum[i]大的元素弹出,然后将i加入队尾。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e6+7;
int a[maxn];
int q[maxn];
const int inf=0x3f3f3f3f;
int main(){
int n,k;
int l=1,r=1;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
a[i]+=a[i-1];
}
q[1]=0;
int res=-inf;
for(int i=1;i<=n;++i){
while(l<=r&&q[l]<i-k) ++l;
res=max(res,a[i]-a[q[l]]);
while(l<=r&&a[q[r]]>=a[i]) --r;
q[++r]=i;
}
printf("%d\n",res);
return 0;
}
本文深入探讨了单调队列的概念及其在滑动窗口问题中的应用。通过具体实例,如求解滑动窗口中最大子数组和的问题,阐述了如何利用单调队列维护下标递增及值的递增或递减特性,实现高效求解。
932

被折叠的 条评论
为什么被折叠?



