单调队列
单调队列
一、定义
单调队列里的元素是单调递增或者单调递减的
二、实现
双端队列 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 扫描