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

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

博客推荐

用法及作用: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
", 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
", lt[i], rt[i]);
	}
    return 0;
}
原文地址:https://www.cnblogs.com/alking1001/p/12299121.html