题目传送门

一、单调栈原理

单调栈里装的是什么?

动态维护一个栈,把后续问题的答案都维持在这个栈中,把肯定不再有用的数字从栈中干掉。

二、理解与感悟

1、 动态维护,随进随维护,不是预处理。

2、可以将\(O(N^2)\)的时间复杂度降为\(O(N)\)

3、此类“左侧(或右侧)最近”,比自己大的(或小的),用单调栈。

4、为什么说明单调的呢?
下面举一个栗子:
(1) 5 4 3 2 1
栈内就是
1 2 3 4 5 单调上升的

(2) 5 4 2 1 2
2入栈 栈内:2
1比2小,2找到答案1,2出栈,1入栈 栈内:1
2比1大,2入栈 栈内:1 2
4比2大,4入栈 栈内:1 2 4
5比4大,5入栈 栈内:1 2 4 5

总结:单调上长栈

三、左边第一个比我小

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
int n;
int a[N];
int stk[N], tt; //栈内容:待查找答案的数字
int res[N];     //记录“左边比我小的数字”编号

/**
 测试用例:左边第一个比我小
 6
 6 10 3 7 4 12

 结果:
 -1 6 -1 3 3 4
 */
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    //倒序遍历,寻找左侧比自己小的数字
    for (int i = n; i >= 1; i--) {
        while (tt && a[stk[tt]] > a[i]) {//栈不空并且当前元素i是栈顶元素左侧并且比栈顶元素小的第一个数
            res[stk[tt]] = i;            //为栈顶元素记录答案i
            tt--;                        //栈顶元素出栈
        }
        stk[++tt] = i;                   //将i入栈,准备查找它左侧比它小的数字
    }
    //res[i]中装的是序号,是1~n的,所以可以用res[i]>0进行判断是否找到
    //a[res[i]]是原始的数据值,是res[i]位置上的值
    for (int i = 1; i <= n; i++) res[i] ? cout << a[res[i]] << ' ' : cout << "-1 ";
    return 0;
}

四、右侧第一个比自己大的

#include <bits/stdc++.h>

using namespace std;
const int N = 100010;
int n;
int a[N];
int stk[N], tt;
int res[N];

/**
测试用例:右边第一个比我大
6
6 10 3 7 4 12

结果:
10 12 7 12 12 -1
*/
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    //答案是查找右侧的,所以正序遍历
    for (int i = 1; i <= n; i++) {
        while (tt && a[stk[tt]] < a[i]) {//栈内装的是没有找到答案的数字
            res[stk[tt]] = i;
            tt--;
        }
        stk[++tt] = i;
    }
    for (int i = 1; i <= n; i++) res[i] ? cout << a[res[i]] << ' ' : cout << "-1 ";
    return 0;
}

五、视频讲解

https://www.ixigua.com/6925435220292436494

相关文章:

猜你喜欢
  • 2022-12-23
  • 2021-12-18
  • 2021-11-14
相关资源
相似解决方案