[算法总结] 单调栈

定义

顾名思义,单调栈即满足单调性的栈结构。

例题分析:

Acwing 830. 单调栈

-------------------传送门--------------------------

思路分析


我们可以通过来存放

当前数小的数

(才发现还挺难 没讲明白)

code:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n ;
    cin>>n;
    stack<int> stk;
    while( n -- )
    {
        int x;
        cin>>x;
        while(stk.top()>=x && !stk.empty())
            stk.pop();

        if(!stk.empty())
            cout<<stk.top()<<" ";
        else
            cout<<-1<<" ";
        stk.push(x);

    }
    return 0;
}

习题1. 131. 直方图中最大的矩形

(做这题之前建议先 回顾 Acwing 830. 单调栈 )

思路:

我们可以以当前的高度, 向左右两边扩展 (只高度>= 自己的 面积才能加进来)

所以这样子问题就转换成为 :
当前这个数左边第一个比它小的数
当前这个数右边第一个比它小的数

所以我们就可以进行操作了
在这里插入图片描述

code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =  1e5+10;
int h[N],l[N],r[N];
stack<int> stk;
int main()
{
    int n;
    while(cin>>n)
    {
        if(n == 0)
            break;
        for(int i = 1; i<=n ; i++)
            scanf("%d",&h[i]);

        h[0] = h[n+1] = -1; ///控制边界

        stk.push(0);///控制边界
        
        for(int i= 1; i<=n ; i++)
        {
            while(h[stk.top()] >= h[i]) stk.pop(); ///单调栈左边找最小的应用
            l[i] = stk.top();
            stk.push(i);
        }

        while(!stk.empty()) stk.pop();

        stk.push(n+1);
        for(int i=n; i>0 ;i --)
        {
            while(h[stk.top()] >= h[i]) stk.pop(); ///数组反过来求 一遍单调栈左边做小的 便是右边最小的了
            r[i] = stk.top();
            stk.push(i);
        }

        long long ans = 0;
        for(int i=1; i<=n ; i++ )
        ans = max(ans,(ll) h[i]*(r[i] - l[i] - 1)); ///计算面积

        cout<<ans<<endl;
    }
    return 0;
}

这是菜鸟(是本人)的话

我是先做完了单调栈的代码,才过来看这题的,cf分数已经1300了

考虑这题的时候,的确努力的在往单调栈这边靠,

因为没怎么懂单调栈,所以我就一直卡在 用高度大的去和高度小的去计算 ? 无可厚非

我脑子里一个 擎天柱的想法把我给扼杀了 也就是 如果一个很高很高的 那么如果被小的限制了,那么就wa了

正是因为这个想法让我的思路偏向dp了

对于每一个f[i] (表示当前的最大面积) max(和自己小的去交集,本身自己的面积)

但是还是感觉不行,就是感觉这个状态转移错了,因为他既能被后面的影响也可以被前面的,同时做法好像是o n^2的 所以就摒弃了

最后还是选择看y总,只能说我的思路就差一步了,走偏了,应该是大定小,而不是大去依赖小

没想到最后还是转换成 (左边第一个最小的模型)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值