学习过栈后,咱们再来介绍一个新的知识点——单调栈。
咱们先回顾一下栈的知识:
1.先进后出
好像没了
那单调栈的意思其实就是很简单:
栈中元素满足某种单调性
常见的单调栈包括:单调递增、单调递减
下面咱们来看一个单调递增的例子
将 2 5 3 7 4 8 9 插入到栈中,维护一个单调递增的栈
这里的话,我们用数组模拟一下单调栈:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
int a[N],tt;
int main()
{
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
if(x>a[tt]) a[++tt] = x;
}
for(int i =tt;i>0;i--) printf("%d ",a[i]);
return 0;
}
/*
7
2 5 3 7 4 8 9
*/
洛谷题:https://www.luogu.com.cn/problem/P5788
#include<bits/stdc++.h>
using namespace std;
const int N = 3e6+10;
int n;
int a[N],s[N],tt,ans[N],b[N];
int main()
{
scanf("%d",&n);
for(int i =1;i<=n;i++) scanf("%d",&a[i]);
for(int i =n;i>=1;i--)
{
while(tt && a[i]>=s[tt])tt--;
ans[i] = b[tt];
s[++tt] = a[i];
b[tt] = i;
}
for(int i =1;i<=n;i++)
{
printf("%d ",ans[i]);
}
return 0;
}
1.首先,我们应该考虑,我们维护的是一个什么性质的单调栈
题目中指出,我们输出的是第 i个元素之后第一个大于 a[ i ] 的元素的下标。
我们考虑,如果,我们正序入栈,维护一个递增序列的话,一旦遇到原序列的的值小于栈顶元素,那我们将无法获得该值在序列中的后面第一个比自己大的数。
因此我们考虑倒序入栈,维护一个递减序列。
2.考虑如何获取下标:
这个很简单,我们只需要在插入一个元素的时候,存下该元素对应的序号就好了。此时,我们只需要维护一个普通的栈就好了。