单调栈 & 单调队列
单调栈
引入
单调栈是什么?顾名思义,单调栈即满足单调性的栈结构,与单调队列相比,其只在一端进行进出。
过程
插入
将一个元素插入单调栈时,为维护栈的单调性,需要在保证将该元素插入到栈顶后整个栈满足单调性,并且使弹出的元素最少
伪代码
insert x
while !sta.empty() && sta.top()<x
sta.pop()
sta.push(x)
单调栈例题
代码实现
#include<bits/stdc++.h>
using namespace std;
int n,a[3000005],b[3000005];
stack <int> s;
int main()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=n;i>=1;i--)
{
while(!s.empty() && a[s.top()] <= a[i])
{
s.pop();//弹出栈顶比当前数小的
}
if(!s.empty())
{
b[i] = s.top();
}
else
{
b[i] = 0;
}
s.push(i);
}
for(int i = 1;i <= n;i++)
{
cout << b[i] << " ";
}
return 0;
}
定义也是直接抄OI Wiki
单调队列
引入
首先我们要看一道经典例题,滑动窗口
最暴力的想法很简单,对于每一段 i~i+k-1 的序列,逐个比较来找出最大值(和最小值),时间复杂度约为 O(n * k)。
很显然,这其中进行了大量重复工作,除了开头 k-1 个和结尾 k-1 个数之外,每个数都进行了 k 次比较,而题中 100% 的数据为 n <= 1000000,当 k 稍大的情况下,显然会 TLE。
这时所用到的就是单调队列了。
定义
顾名思义,单调队列的重点分为「单调」和「队列」。
单调 指的是元素的规律递增(或递减)。
队列 指的是元素只能从队头和队尾进行操作。
例题分析
没错,它在这里
代码奉上
//1、维护队首(就是如果你已经是当前的m个之前那你就可以被删了,head++)
//2、在队尾插入(每插入一个就要从队尾开始往前去除冗杂状态)
#include<bits/stdc++.h>
using namespace std;
int n,m;
int q1[1000001],q2[1000001];
int a[1000001];
int min_deque()
{
int h = 1,t = 0;
for(int i = 1;i <= n;i++)
{
while(h <= t && q1[h] <= i - m) h++;
while(h <= t && a[i] < a[q1[t]]) t--;
q1[++t] = i;
if(i >= m ) cout << a[q1[h]] << " ";
}
cout << "\n";
return 0;
}
int max_deque()
{
int h = 1,t = 0;
for(int i = 1;i <= n;i++)
{
while(h <= t && q2[h] <= i - m) h++;
while(h <=t && a[i] > a[q2[t]]) t--;
q2[++t] = i;
if(i >= m) cout << a[q2[h]] << " ";
}
return 0;
}
int main()
{
cin >> n >> m;
for(int i = 1;i <= n;i++) cin >> a[i];
min_deque();
max_deque();
return 0;
}