[笔记]单调栈
单调栈,顾名思义就是存储在栈中的元素是具有单调性的(单调递增或单调递减),根据不同的要求进行维护
来看看洛谷的板子题.题目要求找第一个比当前数大的数的序号.
一开始我手推了一下,发现了如何实现单调栈,拿样例来看:栈里面先\(push\)进去\(1\),接着读取到了\(4\),发现它比栈顶元素大,就弹出\(1\),加入\(4\),而1对应的答案也就是\(4\),下标为\(2\).接着读取的是\(2,3\),这两个数放入栈中不会破坏单调性,直到读取到\(5\),它比栈里面所有的元素都打,所以栈里面所有元素的答案都是\(5\),栈被清空,栈中加入\(5\),而此时\(5\)是最后一个元素,所以它的答案是\(0\).
这样基本的思路就出来了.在实现的时候我一开始遇到了问题,我最初写的是直接用栈来维护序列的数值,再用一个\(map\)来映射标号,记录答案,但由于\(STL\)等奇奇怪怪的原因导致了\(TLE\).看过题解后我发现其实可以直接用栈来维护下标,在判断的时候将栈内元素作为下标来比较即可,还是我太菜了~~
总体而言,单调栈还是比较简单,只是根据问题的不同会有变化,只做模板题是肯定不够的,还要在以后的练习中灵活变通
代码如下
#include <bits/stdc++.h>
using namespace std;
stack < int > s;
long long a[3000010];
long long ans[3000010];
int main(){
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
scanf("%lld",&a[i]);
}
s.push(1);
for(int i = 2;i <= n;i++){
while(!s.empty() && a[i] > a[s.top()]){
ans[s.top()] = i;
s.pop();
}
s.push(i);
}
for(int i = 1;i < n;i++){
printf("%lld ",ans[i]);
}
printf("0\n");
return 0;
}