单调栈入门

匿名 (未验证) 提交于 2019-12-02 23:52:01

分为单调递增和单调递减栈。(栈内元素成递增或者递减性)

例如:
当前单调递增栈内元素[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);     } }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!