单调栈算法 入门+博客推荐+模板
博客推荐
用法及作用: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