单调栈
视频连接
#include<iostream>
using namespace std;
const int N = 100010;
int stk[N], tt;
int main() {
int n;
cin >> n;
while (n--) {
int x;
scanf("%d", &x);
//如果栈顶元素大于当前待入栈 元素,则出栈
while (tt && stk[tt] >= x)
tt--;
//如果栈空,则没有比该元素小的值
if (!tt)
printf("-1");
else
printf("%d", stk[tt]);
//最后要把读入的数放入栈中,因为它还有机会成为答案
stk[++tt] = x;
}
}
单调队列
滑动窗口
#include <iostream>
using namespace std;
const int N = 1000010;
//a[N]数组就是输入的原型数组
//q[N]数组是保存单调队列的数组,但是是通过保存下标来保存单调队列的。
int a[N], q[N], hh, tt = -1;
//hh是单调队列的队头,tt是单调队列的队尾
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++)
{
cin >> a[i]; //向原型数组中录入数据
if (i - k + 1 > q[hh]) hh++;
//这里很重要,i-k+1是什么?i - k + 1 是滑动窗口的做左侧的坐标。
// 这个坐标要是大于q[hh]说明q数组队头元素已经出了窗口之外了,也就是取不到了直接出队就行了
while (hh <= tt && a[i] <= a[q[tt]]) tt--;
//这里在求最小值,a[i] <= a[q[tt]]就是代表只要队尾的元素大于a[i]就出队,
// 因为求的是最小值,所以大于的就可以直接出对了,反正取最小值也轮不到他们
q[++tt] = i;
if (i + 1 >= k) cout << a[q[hh]] << " ";
//i + 1代表什么?i + 1就是原型数组的实际长度,只要实际长度大于k了说明,
// 原型数组中最起码可以出现一个滑动窗口了,就可以开始输出值了
}
//求最大值思路类似,改个判断就行了
cout << endl;
hh = 0;
tt = -1;
for (int i = 0; i < n; i++)
{
if (i - k + 1 > q[hh]) hh++;
while (hh <= tt && a[i] >= a[q[tt]]) tt--;
q[++tt] = i;
if (i + 1 >= k) cout << a[q[hh]] << " ";
}