单调栈

今天小初来说说单调栈,关于此算法,小初还是有很多不足之处,还请求有人能够指出来

介绍

单调栈顾名思义,就是栈中元素呈现单调性。而所谓单调就和数学里的定义一样,是一列数从小到大排列或从大到小来排列,所以我们阔以想象单调栈就是栈里面的数是完全有序的。

应用

小初在刚刚得知这个算法的时候是一脸懵的,觉得没有什么用呀,但是仔细想想,这个算法的实用性还是比较高的。
我们先把单调栈的性质列举出来
1.单调栈里的元素具有单调性
2.元素加入栈前,会在栈顶端把破坏栈单调性的元素都删除
3.使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的元素。
(也就是说在元素进栈前他向左拓展的区间已经确定,在出栈前她能向右拓展的区间也能确定)
那么我们阔以根据这些性质把应用列举出来,如下:
1.最基础的应用就是给定一组数,针对每个数,寻找它和它右边第一个比它大的数之间有多少个数。
2.给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列的长度最大。
3.给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列所有元素和最大。

例题

我们来康康小初写的第一个关于单调栈应用的题目
小初的直达车

题解

由题意可得,这道题是关于小初列举的第二个应用,而要求出最大的矩形面积,也就是基本的长乘宽,因为纸片的宽度恒为1,所有我们只需要考虑用户输入的纸片长度,参考本题的时间限制和数据大小,所有我们必须要控制迭代次数,本题的思路其实很简单,就是找出在用户输入的长度,往左右边找比其长度小的纸片,因为如果左右两边的纸片大于或等于该纸片,那么矩形就阔以沿着左右两边进行扩散,这样我们就知道了矩形的宽度,而长度就是用户输入的值,只要将所有的长乘以宽并找出最大的就行了,是不是很简单呢,小初青涩的代码如下:

#include<stdio.h>
#include<string.h>
long long int r[100100];//记录左边界
long long int l[100100];//记录右边界
long long int h[100100];//记录纸片高度
long long int xh[100100];//记录位置
int main(void)
{
    int n,i,j,k,t;
    long long int a,b,end;
    while(1)
    {
        scanf("%d",&n);
        if(n==0)
            break;
        for(i=1; i<=n; i++)
            scanf("%lld",&h[i]);
        xh[0]=t=0;//寻找左边界
        h[0]=-1;//将不存在的最左边设置为-1,表示栈为空时一定能够入栈,下同
        for(i=1; i<=n; i++)//对该纸片的左边进行入栈出栈,规律是将破坏单调递增的数出栈,合法的入栈,下同
        {
            while(h[xh[t]]>=h[i])
                t--;
            l[i]=xh[t];
            xh[++t]=i;
        }
        t=0;
        xh[0]=n+1;//寻找右边界
        h[n+1]=-1;
        for(i=n;i>0;i--)//同上
        {
            while(h[xh[t]]>=h[i])
                t--;
            r[i]=xh[t];
            xh[++t]=i;
        }
        for(i=1;i<=n;i++)//寻找最大值
        {
            if(i==1)
                end=(r[i]-l[i]-1)*h[i];
            else
            {
                a=(r[i]-l[i]-1)*h[i];
                if(a>end)
                    end=a;
            }
        }
        printf("%lld\n",end);
    }
}

那么,单调栈就暂时告一段落啦。谢谢浏览。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值