单调队列

一个支持在队尾插入,队头和队尾删除的队列,整个队列呈单调性

如果要求最大值则维护一个递减的单调队列,最小值则递增

用deque写很方便(前几天用数组模拟队列 代码调不出bug难受死了)

例题 P1886 滑动窗口

思路:

用一个deque,存点的序号(用于判断是否过期)和点的数字。每次新增加一个元素,都要判断

1.前面的点是否过期,过期弹出

2.新加入元素是否比队尾元素的数字大,若大 新加入的元素既时间上比队尾元素更优,数字上也更优,那么弹出队尾元素,一直弹到找到一个比新元素更大的队尾元素或队列为空为止(求最大值的情况)

然后每次输出即可

代码:

#include<iostream>
#include<cstdio>
#include<deque>
using namespace std;
struct node{
    int tim,number;
}; 
deque<node> qmin,qmax;
const long long N=1e6+10;
int n,k,a[N],ansmin[N],ansmax[N],cnt=0;
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        while(!qmin.empty()&&qmin.front().tim<(i-k+1)) qmin.pop_front();
        while(!qmax.empty()&&qmax.front().tim<(i-k+1)) qmax.pop_front();
        while(!qmin.empty()&&qmin.back().number>a[i]) qmin.pop_back();
        while(!qmax.empty()&&qmax.back().number<a[i]) qmax.pop_back();
        node h;
        h.number=a[i];
        h.tim=i;
        qmax.push_back(h);
        qmin.push_back(h);
        if(i>=k){
            ansmin[++cnt]=qmin.front().number;
            ansmax[cnt]=qmax.front().number;
        }
    }
    for(int i=1;i<=cnt;i++){
        printf("%d ",ansmin[i]);
    }
    printf("\n");
    for(int i=1;i<=cnt;i++){
        printf("%d ",ansmax[i]);
    }
    return 0;
} 

最近一直在看板子,但感觉学了新东西之后并不能把他们综合运用到一个题上(本来也什么都不会呢=D),可能需要多加练习?还是我脑子太笨了TT

posted @ 2023-08-03 13:21  dgdger  阅读(15)  评论(0编辑  收藏  举报