数据结构
单调队列使用的是一种在一端可以出队,另一端可以出队和入队的队列,其中只能出队的作为队头,既能出队又能入队的称为队尾。如下图:
用途
求区间最大(最小)值
实现
最大值
区间内的数保证单调递减,此时队头为此区间的最大值。
队头:队头出队用来维护区间大小。
队尾:队尾出队入队用来维护区间单调性。
为什么要使队列内的数单调递减?因为队列内存储的数都是有可能成为区间最大值的数。或者说队列中存储的数是(最大值,第二大,第三大。。。),所以要单调递减。
最小值
区间内的数保证单调递增,此时队头为此区间的最小值。
队头:队头出队用来维护区间大小。
队尾:队尾出队入队用来维护区间单调性。
为什么要使队列内的数单调递增?因为队列内存储的数都是有可能成为区间最小值的数。或者说队列中存储的数是(最小值,第二小,第三小。。。),所以要单调递增。
P1886 滑动窗口 /【模板】单调队列
#include<cstdio>
#include<iostream>
#include<vector>
#include<iomanip>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iterator>
using namespace std;
struct Node {
int id;
int val;
};
int n, k;
int num[1000005];
Node q[1000005]; //队列
void getmax() {
int f = 1;
int r = 0;
for (int i = 1; i <= n; i++) {
while (f <= r && q[f].id + k <= i)f++; //队头出队,保证队列内的数是当前区间的数
while (f <= r && q[r].val < num[i])r--; //队尾出队,保证单调递减
r++;
q[r].id = i;
q[r].val = num[i];
if (i >= k)cout << q[f].val<<" ";
}
}
void getmin() {
int f = 1;
int r = 0;
for (int i = 1; i <= n; i++) {
while (f <= r && q[f].id + k <= i)f++; //队头出队,保证队列内的数是当前区间的数
while (f <= r && q[r].val > num[i])r--; //队尾出队,保证单调递增
r++;
q[r].id = i;
q[r].val = num[i];
if (i >= k)cout << q[f].val << " ";
}
}
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> num[i];
}
getmin();
cout << endl;
getmax();
return 0;
}