定义
从栈底元素到栈顶元素呈单调递增或单调递减,栈内序列满足单调性的栈。
原理
(1)当新元素在单调性上优于栈顶时(单增栈新元素比栈顶大,单减栈新元素比栈顶小),压栈,栈深+1;
(2)当新元素在单调性与栈顶相同(新元素于栈顶相同)或劣于栈顶时(单增栈新元素比栈顶小,单减栈新元素比栈顶大),弹栈,栈深-1;
注:栈里存的是位序,比较的是位序对应的值
例如:
1 5 2 3 7 4 值 序号 1-->5 1-->2 1-->2 1-->3 1-->2-->3 1-->3-->4 1-->2-->3-->7 1-->3-->4-->5 1-->2-->3-->4 1-->3-->4-->6
功能
例如:求序列1 5 2 3 7 4中,每个元素左边第一个严格小于本身的值的位置
其实答案就在上面,就是插入当前值时栈顶的值。
但其正确性却不好证明
这样看,如果一个元素其右边有更小的数,该元素一定会被弹出栈(为什么可以这样?因为找到更小的了,该元素对后面的就没有影响了)。
这样“去杂”以后栈就是单调的了,如果栈顶元素小于当前元素,栈顶的值就答案,当前元素入栈(可能有用,对后面还有影响);如果大于或等于,用当前元素更新栈,停下来的地方也正好是答案(单调,左边更小,所以当前是第一个最小)。
模板
得到序列中n个元素向左遍历的第一个比它小的数的位置
1 const int maxn = 100000 + 10; 2 int n,a[maxn]; 3 int l[maxn]; 4 5 void solve() 6 { 7 stack<int>s; 8 for (int i = 1; i <= n; i++) 9 { 10 while (!s.empty() && a[s.top()] >= a[i]) s.pop(); 11 if (s.empty()) l[i] = 0; 12 else l[i] = s.top(); 13 s.push(i); 14 } 15 }
例题
Largest Rectangle in a Histogram (POJ No.2599)
柱状图是由一些宽度相等的长方形下端对齐后横向排列得到的图形。现有由n个宽度为1,高度分别为h1、h2...hn的长方形从左到右依次组成的长方形。问里面包含的长方形的最大面积是多少。
例如:n = 7,h = {2,1,4,5,1,3,3}
代码实现
1 #include<stdio.h> 2 #include<iostream> 3 #include<stack> 4 using namespace std; 5 6 const int maxn = 100000 + 10; 7 int n,hi[maxn]; 8 int l[maxn],r[maxn]; 9 10 void l_solve() //得到l[i] 11 { 12 stack<int>s; 13 for (int i = 1; i <= n; i++) 14 { 15 while (!s.empty() && hi[s.top()] >= hi[i]) s.pop(); 16 if (s.empty()) l[i] = 0; 17 else l[i] = s.top(); 18 s.push(i); 19 } 20 } 21 22 void r_solve() //得到r[i] 23 { 24 stack<int>s; 25 for (int i = n; i >= 1; i--) 26 { 27 while (!s.empty() && hi[s.top()] >= hi[i]) s.pop(); 28 if (s.empty()) r[i] = n + 1; 29 else r[i] = s.top(); 30 s.push(i); 31 } 32 } 33 34 int main() 35 { 36 while (scanf("%d",&n) == 1 && n) 37 { 38 for (int i = 1; i <= n; i++) 39 scanf("%d", &hi[i]); 40 l_solve(); r_solve(); 41 long long ans = 0; 42 for (int i = 1; i <= n; i++) 43 { 44 long long tmp = (long long)hi[i] * (r[i] - l[i] - 1); 45 if (tmp > ans) ans = tmp; 46 } 47 printf("%lld ", ans); 48 } 49 return 0; 50 }
参考链接:https://blog.csdn.net/wubaizhe/article/details/70136174