分为单调递增和单调递减栈。(栈内元素成递增或者递减性)
例如:
当前单调递增栈内元素[1,2,4],之后入栈的元素为(3),
为了维护单调性,元素(4)出栈
\[ [1,2,4]-入栈(3) -出栈(4)- [1,2,3]-入栈(0)-出栈(1)(2)(3)-[0] \]
把序列中每个元素放到单调栈中进行维护就可以在\(O(n)\)时间复杂度内
求出区间每个元素为最大值/最小值时,影响的区间范围为[left,right]。
单调递增栈求最小值影响范围
单调递减栈求最大值影响范围
\(例如:序列{1,2,3,2,1}\)
    1 2 3 2 1
        口
      口口口
    口口口口口
    0 1 2 3 4用单调递减栈即可求出
| 最大值 | 区间[left,right] | 
|---|---|
| 1 | [0,0] | 
| 2 | [0,1] | 
| 3 | [0,4] | 
| 2 | [3,4] | 
| 1 | [4,4] | 
我们规定将下标(index)压入栈中。为了方便编码,我们在使用单调栈的数组的最后加入-INF(一个极小值),方便后续的出栈。
序列变成 \({1,2,3,2,1,-INF}\)
| i | 要入栈的height[i] | 栈的变动 | 变动后的栈 | 
|---|---|---|---|
| 0 | 1 | push(0) | [0] | 
| 1 | 2 | push(1) | [0,1] | 
| 2 | 3 | push(2) | [0,1,2] | 
| 3 | 2 | pop(2),push(3) | [0,1,3] | 
| 4 | 1 | pop(3),pop(1),push(4) | [0,4] | 
| 5 | -INF | pop(0),push(4) | [] | 
若元素height[i]从栈中pop出就说明这个元素为最小值的右侧影响范围到此为止。
因为栈内元素单调递增,栈pop之后,栈顶的元素height[s.top()]不大于pop的元素。所以左侧的影响范围为pop之后栈顶的元素的下标+1,这里需要注意pop之后栈为空的情况,因为pop之后栈为空,说明没有元素是比pop出的这个元素小,那这个pop出的元素影响它左端的所有元素。
//单调递增栈
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long int LL;
const int MAXN = 1e6 + 1;
LL height[MAXN];
int N;
void solve(){
    height[N] = -INF;
    stack<int> s;
    for(int i=0;i<=N;i++){
        while(!s.empty() && height[s.top()] > height[i]){
            int cur = s.top();
            s.pop();
            int _left = s.empty()?0:s.top()+1;
            int _right = i-1;
            cout << height[cur] << " " << _left << " " << _right << endl;
        }
        s.push(i);
    }
}
int main() {
    cin >> N;
    for(int i=0;i<N;i++) cin >> height[i];
    solve();
    return 0;
}//单调递减栈
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long int LL;
const int MAXN = 1e6 + 1;
LL height[MAXN];
int N;
void solve(){
    height[N] = INF;
    stack<int> s;
    for(int i=0;i<=N;i++){
        while(!s.empty() && height[s.top()] < height[i]){
            int cur = s.top();
            s.pop();
            int _left = s.empty()?0:s.top()+1;
            int _right = i-1;
            cout << height[cur] << " " << _left << " " << _right << endl;
        }
        s.push(i);
    }
}
int main() {
    cin >> N;
    for(int i=0;i<N;i++) cin >> height[i];
    solve();
    return 0;
}void solve(){
    //单调递增栈 -INF,递减 INF
    height[N] = -INF;
    stack<int> s;
    for(int i=0;i<=N;i++){
        //单调递增栈 >,递减 <,等号看题目
        while(!s.empty() && height[s.top()] > height[i]){
            int cur = s.top();
            s.pop();
            int _left = s.empty()?0:s.top()+1;
            int _right = i-1;
            cout << height[cur] << " " << _left << " " << _right << endl;
        }
        s.push(i);
    }
}原文:https://www.cnblogs.com/--zz/p/11247874.html