单调栈算法 入门+博客推荐+模板

白昼怎懂夜的黑 提交于 2020-02-12 15:15:51

单调栈算法 入门+博客推荐+模板

博客推荐

用法及作用:https://www.cnblogs.com/lher/p/7620330.html

简介

首先需要明确定义:1.单调递增的栈,2.单调递减的栈

  1. 单调递增的栈:从栈顶到栈底是递增的,每次压进去的数要小于栈顶元素,输出也是单调递增的,主要是解决最大值的区间问题;
  2. 单调递减的栈:从栈顶到栈底是递减的,每次压进去的数要大于栈顶元素,输出也是单调递减的,主要是解决最小值的区间问题;

这里的单调性是否严格,要根据实际情况来做决定。

在一个数列中,单调栈解决的是以某个值为最小(最大)值的最大区间,也就是我们需要知道当以这个值为最小值时,在这个数列中的左右区间是什么。

模板

//求最小值时的区间,使用单调递减栈
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
const double esp=1e-6;
const int inf=0x3f3f3f3f;
const int MAXN=1E5+7;
ll num[MAXN], st[MAXN];
int n, top, lt[MAXN], rt[MAXN];
int main()
{
    //这里是求正数数列的
    while(scanf("%d",&n) && n!=0)
    {
        top=0; st[top]=0; //预处理
        num[0]=-1; num[n+1]=-1;//预处理,因为输入的数都是正数,所以这个是最小的数
        for(int i=1; i<=n; i++)
            scanf("%lld", &num[i]);
        for(int i=1; i<=n+1; i++)//这里多一个是为了全部输出
        {
            lt[i]=i;
            rt[i]=i;
            while(num[st[top]] > num[i]) //栈顶元素大于要进栈的数
            {
                rt[st[top]] = i-1;
                lt[i] = lt[st[top]];
                top--;   
            }
            if(num[st[top]] == num[i]) lt[i] = lt[st[top]];//很重要的,很巧妙的代码
            st[++top]=i;//大于等于栈顶的数进栈。
        }
        for(int i=1; i<=n; i++)
            printf("%d %d\n", lt[i], rt[i]);
    }
    return 0;
}
//求最大值时的区间,使用单调递增栈,小于等于栈顶的数进栈
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
const double esp=1e-6;
const int inf=0x3f3f3f3f;
const int MAXN=1E5+7;
ll num[MAXN], st[MAXN];
int n, top, lt[MAXN], rt[MAXN];
int main()
{
    while(scanf("%d",&n) &&n!=0)
    {
        top=0; st[top]=0;
        num[0]=-1; num[n+1]=-1;
        for(int i=1; i<=n; i++)
            scanf("%d", &num[i]);
        for(int i=1; i<=n+1; i++)
        {
            lt[i]=i;
            rt[i]=i;
            while(num[st[top]] < num[i])
            {
                rt[st[top]]=i-1;
                lt[i]=lt[st[top]];
                top--;
            }
            if(num[st[top]] == num[i])
                lt[i] = lt[st[top]];
            st[++top]=i;
        }
        for(int i=1; i<=n; i++)
            print("%d %d\n", lt[i], rt[i]);
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!