单调栈

单调递增或单调减的栈,跟单调队列差不多,但是只用到它的一端,利用它可以用来解决一些ACM/ICPC和OI的题目,如RQNOJ 的诺诺的队列等。

单调栈是一种特殊的栈,栈内元素保存单调性

作用:

利用单调栈,可以找到向左/右遍历第一个比它小/大的元素的位置

以向左遍历第一个比它小的点为例:

我们要求左边最近的比a[i]小的点的位置,呢么我们栈中元素应该是要比a[i]小的,如果没有,呢么就没找到,就是0

  1. 判断栈中元素是否比a[i]大,如果大就一直弹出,直到空为止
  2. 如果栈为空,呢么标记左边没有比它小的元素,否则stack.top()就是向左遍历第一个比它小的点
  3. 压入a[i].

5

1 3 4 2 5

(1)1.size()==0不做   2.  0    3. 压入1

(2)1. 1<3 无需弹出    2.  1   3.压入3

(3)1.  3<4 无需弹出   2.  2    3.压入4

(4)1.  4>2,3>2 弹出4,弹出3  2.1   压入2

(5) 1.   2<5    2.   4    压入5

代码:

向左遍历第一个比它小的,呢么单调栈是正序的,sk.top()<a[i]

向左遍历第一个比它大的,呢么单调栈是正序的,sk.top()>a[i]

向右仅仅把遍历顺序改变即可

向左遍历第一个比它小的点:

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
stack<int> sk;
int a[MAXN];
int ans[MAXN];

int main()
{
    int n,x,y;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        while(sk.size()&&a[sk.top()]>=a[i])
            sk.pop();
        if(sk.empty())//左边没有,呢么就是0
            ans[i]=0;
        else
            ans[i]=sk.top();
        sk.push(i);
    }
    for(int i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}

向左遍历第一个比它大的点:

for(int i=1;i<=n;i++)
{
    while(sk.size()&&a[sk.top()]<=a[i])
        sk.pop();
    if(sk.empty())
        ans[i]=0;
    else
        ans[i]=sk.top();
    sk.push(i);
}

向右遍历第一个比它大的点:

for(int i=n;i>=1;i--)
    {
        while(sk.size()&&a[sk.top()]<=a[i])
            sk.pop();
        if(sk.empty())
            ans[i]=0;
        else
            ans[i]=sk.top();
        sk.push(i);
    }

向右遍历第一个比它小的点:

for(int i=n;i>=1;i--)
    {
        while(sk.size()&&a[sk.top()]>=a[i])
            sk.pop();
        if(sk.empty())
            ans[i]=0;
        else
            ans[i]=sk.top();
        sk.push(i);
    }

题目:https://blog.youkuaiyun.com/weixin_41183791/article/details/89431494

        https://blog.youkuaiyun.com/weixin_41183791/article/details/89298010

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值