单调栈
单调栈有单调递增栈和单调递减栈,但实现原理都差不多
单调递增栈是如果当前元素大于栈顶元素则入栈,否则弹出栈顶元素,直到栈为空或者栈顶元素小于当前元素。
单调递减栈类似。
主要用解决NGE(Next Greater Element)问题
对序列中每个元素,找到下一个比它大的元素。当然,“下一个”可以换成“上一个”,“比它大”也可以换成“比他小”,原理不变。
附上acwing的板子
#include<iostream>
using namespace std;
int n,stk[100005],tt,x;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
while(stk[tt]>=x)
{
tt--;
}
if(tt)
{
printf("%d ",stk[tt]);
}else
{
printf("-1 ");
}
stk[++tt]=x;
}
}
练习
单调队列
顾名思义维护一个单调的队列,同样也有单调递增队列和单调递减队列
用两个数组维护,一个存队内元素的节点下标,另一个存元素大小
主要用解决在长度为
的序列中,求每个长度为
的区间的区间最值。
附上acwing的板子
#include<iostream>
using namespace std;
const int N=1e6+5;
int n,k,a[N],q[N];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
int hh=0,tt=-1;
for(int i=1;i<=n;i++)
{
if(hh<=tt&&i-q[hh]+1>k) hh++;
while(hh<=tt&&a[i]<a[q[tt]]) tt--;
q[++tt]=i;
if(i>=k) cout<<a[q[hh]]<<" ";
}
cout<<endl;
hh=0,tt=-1;
for(int i=1;i<=n;i++)
{
if(hh<=tt&&i-q[hh]+1>k) hh++;
while(hh<=tt&&a[i]>a[q[tt]]) tt--;
q[++tt]=i;
if(i>=k) cout<<a[q[hh]]<<" ";
}
}