正文
一、特殊的队列
1. 双端队列
字面意思,可以对两端进行 pop
和 push
操作的队列
(1)手写双端队列简述
const int N = 1e6 + 10;
— 队列大小int que[N], head, tail;
— 队列,队首队尾指针head++;
— 弹出队首que[--head] = data;
— 数据data
从队首入队que[head];
— 读取队首数据tail--;
— 弹出队尾que[++tail] = data;
— 数据data
从队尾入队
(2)STL双端队列
#include <deque>
dq[i]
— 访问元素dq.front()
— 返回队首dq.back()
— 返回队尾dq.pop_back()
— 弹出队尾dq.pop_front()
— 弹出队首dq.push_back(e)
— 元素e
从队尾入队dp.push_front(e)
— 元素e
从队首入队
2. 单调队列与滑动窗口
洛谷P1886
题目解析
给定一串序列以及一个窗口大小,要求输出窗口中的最大值与最小值
思路分析
使用单调队列,分两次遍历该序列,时间复杂度 O ( 2 N ) O(2N) O(2N),第一次输出最小值,第二次输出最大值
输出最小值:
- 使用双端队列从队尾存入元素
- 当存入元素比队尾元素小的时候,就将队尾元素pop
- 直到该元素不再比队尾元素小时,再push进入该队列
- 存入数组下标,方便判断是否还在窗口中
- 从队首判断是否属于窗口范围,不属于就pop掉
- 最后输出队首即可,该元素就是 当前窗口中 的 最小值
输出最大值:
具体思路同上,不过在第二步第三步中得到比大小,要选取更大的值
AC代码
#include <bits/stdc++.h>
using namespace std;
#define ONLINE_JUDGE
const int N = 1000010;
int n, m;
int a[N];
deque<int> q;
inline void problem() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d",