审题:
本题是单调栈的模板题
补充:单调栈
单调栈中的数据始终保持单调递增或单调递减
使用情景:给定一个数组,要求寻找
1.某个数左侧,离他最近且值大于他的数
2.某个数左侧,离他最近且值小于他的数
3.某个数右侧,离他最近且值大于他的数
4.某个数右侧,离他最近且值小于他的数
我们先分析情况1:
由于搜索范围是数的左侧,所以我们的遍历顺序是从左往右遍历,要求寻找的数是大于他的,所以我们的栈是单调递减的
代码逻辑分析:
(1)栈顶数据的值小于等于当前数据:说明当前索引位置不存在左侧大于他的数,且当前栈顶数据也不会成为后续的其他数据的要求数(假设其可以成为后续数据的要求数,那么当前遍历到的数据会比他更符合要求,故不可能)
于是我们需要循环进行栈弹出操作,直到栈顶数据值大于当前数据,或栈为空
(2)栈顶数据的值大于当前数据/栈为空:说明找到了要求数,更新ret数组
(3)将当前数据插入到栈中
接下来看看情况2:
搜索范围没变,所以我们还是从左往右遍历,要求寻找的数是小于他的,所以我们采用单调递增的栈
代码逻辑分析:
我们只需要改变一个地方,将情况1代码中的小于等于换成大于等于,大于换成小于即可
然后看看情况3和4:
他们和情况1与2最大的区别就是搜索范围,变为了右侧,所以我们逆着搜索,也就是从右往左搜索
然后我们看看这题属于情况3,所以我们直接写代码即可
#include<iostream> #include<stack> using namespace std; int n; const int N = 3e6 + 10; int a[N],b[N]; void func()//找到该数右侧距离他最近的且比他大的元素的下标 {stack<int> s;for (int i = n; i >= 1; i--)//从右往左遍历{//建立单调递减栈while (s.size() && a[s.top()] <= a[i]){s.pop();}//记录对应元素所拿到的元素下标if (s.size()) b[i] = s.top();else b[i] = 0;//插入下标到栈s.push(i);} } int main() {cin >> n;for (int i = 1; i <= n; i++){cin >> a[i];}func();for (int i = 1; i <= n; i++){cout << b[i] << " ";}return 0; }
注意:
1.栈中存储的是数组对应的下标
P5788 【模板】单调栈 - 洛谷