单调队列

Posted xiaoyezi-wink

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单调队列相关的知识,希望对你有一定的参考价值。

单调队列

一、定义

        单调队列里的元素是单调递增或者单调递减的

 

二、实现

双端队列 deque

支持操作:(1)询问队首/队尾元素   front / back

                  (2)从队首/队尾删除元素  pop_front() / pop_back()

                  (3)从队首/队尾插入元素  push_front() / push_back()

 

三、例题

1.P1886 滑动窗口

题解

以求最小值为例,队列里的元素必须是单调递增的,保证队首是答案,我们每次输出队首

新加入一个元素,如果使得队列非递增,就把前面比他大的全弹出队列

一旦队首元素过了期,也就是窗口划过了它,我们就弹出队首,反正我们还会得到一个新的ans

该输出就输出就行了

 

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstdlib>                                                                             

using namespace std;

inline int read()

    int ans=0;
    char last= ,ch=getchar();
    while(ch<0||ch>9) last=ch,ch=getchar();
    while(ch>=0&&ch<=9) ans=ans*10+ch-0,ch=getchar();
    if(last==-) ans=-ans;
    return ans;


const int maxn=1e6+10;
int n,k;
int a[maxn];
struct node

    int pos,val;
    node(int a,int b) : pos(a),val(b)  //构造函数
 ;
deque<node>p,q;

int main()

    n=read();k=read();
    for(int i=1;i<=n;i++) 
       a[i]=read();
    
    for(int i=1;i<=n;i++)
    
        while(!p.empty() &&p.back().val>a[i] ) p.pop_back() ;
        p.push_back(node(i,a[i]));
        while(p.front().pos<=i-k ) p.pop_front() ;
        if(i>=k) printf("%d ",p.front().val );
    
    printf("\n");
    for(int i=1;i<=n;i++)
    
        while(!q.empty() &&q.back().val<a[i] ) q.pop_back() ;
        q.push_back(node(i,a[i]));
        while(q.front().pos<=i-k ) q.pop_front() ;
        if(i>=k) printf("%d ",q.front().val );
    
    return 0;

 

then,3倍经验

2.P1440 求m区间内的最小值(这题卡ST)

3.P2032 扫描

 

以上是关于单调队列的主要内容,如果未能解决你的问题,请参考以下文章

单调队列 单调栈

优先队列和单调队列一样吗?

单调队列以及单调队列优化DP

数据结构——单调栈&单调队列(解决滑动窗口问题)

单调队列模板

单调队列单调栈