单调队列

单调队列

一、定义

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

 

二、实现

双端队列 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 扫描

 

posted @ 2019-08-02 15:51  晔子  阅读(177)  评论(0编辑  收藏  举报