单调栈算法 入门+博客推荐+模板
博客推荐
用法及作用:https://www.cnblogs.com/lher/p/7620330.html
简介
首先需要明确定义: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;
}
原文地址:https://www.cnblogs.com/alking1001/p/12299121.html
时间: 2024-10-06 02:12:33