文章目录
队列【STL】
队列是只允许在一端
进行插入操作
,在另一端
进行删除
操作的线性表
,简称“队”
队列是一种先进先出
(First In First Out)的线性表
1.队列的STL用法↓
q.push(a)
:插入a到队列q的末尾
q.pop()
:删除队列q的队首元素
q.front()
:查询q的队首元素
q.back()
:查询q的队尾元素
q.size()
:查询q的元素个数
q.empty()
:查询q是否为空
2.队列例题
详见我的另一篇博文:洛谷P2058 [NOIP2016 普及组] 海港
双向队列【deque】(可用于单调队列)
单调队列
是一种主要用于解决滑动窗口
类问题的数据结构,主要用来解决区间最值
问题
时间复杂度为 O ( n ) O\left (n \right ) O(n)
1.deque的STL用法
d.front()
:返回最前一个元素的引用
d.back()
:返回最后一个元素的引用
d.pop_back()
:删除尾部的元素,不返回值
d.pop_front()
:删除头部元素,不返回值
d.push_back(a)
:在队尾添加一个元素a
d.push_front(a)
:在队头添加一个元素a
2.例题:洛谷P1886 滑动窗口/【模板】单调队列
(1)题意解释
有一个长为
n
n
n 的序列
a
a
a,以及一个大小
为
k
k
k 的窗口。现在这个从左边开始向右滑动
,每次滑动一个单位
,求出每次滑动后窗口中的最大值
和最小值
。
(2)题目分析
只需要用两个单调队列
进行维护最小值
和最大值
,然后再用队列进行时效性分析
即可
(3)code↓
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;//定义边界
int n,k,q;//n:n个数,k:区间长度
int ans[3][maxn];//答案数组
struct Pof{
int num,val;//编号和值
};
deque<Pof> mx;//用来求取最大值的单调队列
deque<Pof> mn;//用来求取最小值的单调队列
int main(){
cin>>n>>k;
Pof person;//定义一个名叫person的类
for(int i=1;i<=n;i++){
cin>>q;//输入这个数
person.num=i,person.val=q;//这个数的编号为i,值为q
while(!mx.empty()&&mx.back().val<q){//当队列mx非空且q值比mx的队尾的值小时执行,用于满足单调性
mx.pop_back();//将队尾弹出
}
mx.push_back(person);//将这个类整个压入队列mx
while(i-mx.front().num>=k) mx.pop_front();//如果现在的编号比mx队头的编号之间的差距大于k,就将队头弹出
if(i>=k) ans[1][i-k+1]=mx.front().val;//因为只有大于了k才拥有答案,所以要在编号大于k时记录答案
while(!mn.empty()&&mn.back().val>q){//当队列mn非空且q值比mn的队尾的值大时执行,用于满足单调性
mn.pop_back();//将队尾弹出
}
mn.push_back(person);//将这个类整个压入队列mn
while(i-k>=mn.front().num) mn.pop_front();//如果现在的编号比mn队头的编号之间的差距大于k,就将队头弹出
if(i>=k) ans[2][i-k+1]=mn.front().val;//因为只有大于了k才拥有答案,所以要在编号大于k时记录答案
}
for(int i=1;i<=n-k+1;i++) cout<<ans[2][i]<<" ";//输出区间最小值答案
cout<<endl;
for(int i=1;i<=n-k+1;i++) cout<<ans[1][i]<<" ";//输出区间最大值答案
return 0;
}