单调栈_ios字面意思上理解,栈内元素是单调的,根据题目要求可能是单调递增或递减的。对于一个长度为 n 的序列,如果要求左边第一个比 x 小的数 暴力做法: 但是我们可以有些数是永远不可能被当成答案输出的 例如,如果 6 的后面有 4 ,那么由于 4 比 6 小,且位于更右边,距离待求数更近,所以 6 不可能被当作答案输出。 如果我们把 x 之前的数都存入栈中,每新来一个 x ,就对其进行如下操作: - 如果栈顶元素比 x 大,那么栈顶元素由于更不接近后面待求的数,且和 x 相比更不可能做为答案输出,而被舍弃,pop 出栈



字面意思上理解,栈内元素是单调的,根据题目要求可能是单调递增或递减的



对于一个长度为 n 的序列,如果要求左边第一个比 x 小的数

暴力做法:

for(int i = 0; i < n; ++ i)
{
for(int j = i - 1; j >= 0; --j)
{
if(a[j] < a[i])
{
...;
break;
}
}
}


但是我们可以有些数是永远不可能被当成答案输出的

例如,如果 6 的后面有 4 ,那么由于 4 比 6 小,且位于更右边,距离待求数更近,所以 6 不可能被当作答案输出。

如果我们把 x 之前的数都存入栈中,每新来一个 x ,就对其进行如下操作:

  • 如果栈顶元素比 x 大,那么栈顶元素由于更不接近后面待求的数,且和 x 相比更不可能做为答案输出,而被舍弃,pop 出栈
  • 如果栈顶元素比 x 小,那么栈顶元素就是左边第一个比 x 小的答案
  • 最后将 x 压入栈中

最后对于每一个询问的 x 栈中的数都是单调递增的



例如一个序列

3,2,4,6,5,9,9;栈:空

  1. 询问 3 左边第一个比自己小的数是:-1,因为没有比 3 小的数,此时栈空,3入栈,栈中有:3
  2. 询问 2 左边第一个比自己小的数是:-1,此时 2 比栈顶元素 3 大,3 出栈;因为没有比 2 小的数,此时栈空,2入栈,栈中有:2
  3. 询问 4 左边第一个比自己小的数是:2,因为栈顶元素 2 比 4 小,所以栈顶元素就是答案,4入栈,栈中有:2 4
  4. 询问 6 左边第一个比自己小的数是:4,因为栈顶元素 4 比 6 小,所以栈顶元素就是答案,6 入栈,栈中有:2 4 6
  5. 询问 5 左边第一个比自己小的数是:4,因为栈顶元素 6 比 5 大,所以 6 出栈,紧接着栈顶元素 4 比 5 小,停止出栈,栈顶元素就是答案,5入栈,栈中有:2 4 5
  6. 询问 9 左边第一个比自己小的数是:5,因为 5 比 9 小,栈顶元素就是答案,9 入栈,栈中元素:2 4 5 9
  7. 询问 9 左边第一个比自己小的数是:5,因为栈顶元素 9 大于等于 9 所以,栈顶元素 9 出栈,此时栈顶元素变为 5 比 9 小,所以栈顶元素就是答案,9 入栈,栈中元素:2 4 5 9

单调栈_ios

由于 B 比 A 小,E 比 D 小,且位于更右边,G 等于 F,当位于更右边,所以 A D F都将出栈,剩下蓝色那条单调递增的折线

例题

​830. 单调栈 - AcWing题库​

#include <iostream>
#include <string>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 1e5 + 5;
int stk[N], tt;

int main()
{
int n, x;
scanf("%d", &n);
for(int i = 0; i < n; ++ i)
{
scanf("%d", &x);
while(tt && stk[tt] >= x) --tt;
if(tt) printf("%d ", stk[tt]);
else printf("-1 ");
stk[++tt] = x;
}
return 0;
}