单调栈,顾名思义就是单调递增或者单调递减的栈。
在处理有些数据结构的问题的时候有妙用。
先看一下LeetCode的84题 Largest Rectangle in Histogram
因为这篇博客纯属记录,讲解就省略了。
上代码:(博主一般在LeetCode上用Java,在POJ用C++)
public class Solution { public int largestRectangleArea(int[] heights) { if(heights == null) return 0; if(heights.length == 0) return 0; int res = 0; //递增的单调栈 LinkedList<Integer> s = new LinkedList<Integer>(); //初始化,在栈底放一个-1 s.push(-1); int len = heights.length; for(int i=0;i<len;i++){ while(s.peek()>-1){ if(heights[s.peek()]>heights[i]){ int top = s.pop(); //heights[top]和heights[s.peek()]中间的元素一定比heights[top]大 res = Math.max(res,heights[top]*(i-1-s.peek())); }else{ break; } } s.push(i); } while(s.peek()!=-1){ int top = s.pop(); res = Math.max(res,heights[top]*(len-1-s.peek())); } return res; } }
然后是POJ的2796,因为是左右延伸,所以要用两个单调栈来存储,即Pre和Post。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100000+50; int v[maxn],pre[maxn],post[maxn]; long long sum[maxn]; int main() { int n; while(~scanf("%d",&n)) { v[0]=-1,v[n+1]=-1; memset(sum,0,sizeof(sum)); for(int i=1;i<=n;i++) { scanf("%d",&v[i]); sum[i]=sum[i-1]+v[i]; for(int j=i-1;j>=0; ) { if(v[j]<v[i]) { pre[i]=j+1; break; } j=pre[j]-1; } } for(int i=n;i>=1;i--) for(int j=i+1;j<=n+1; ) { if(v[j]<v[i]) { post[i]=j-1; break; } j=post[j]+1; } long long ans=-1,l,r; for(int i=1;i<=n;i++) { long long temp=(sum[post[i]]-sum[pre[i]-1])*v[i]; if(temp>ans) { ans=temp; l=pre[i]; r=post[i]; } } printf("%lld\n%lld %lld\n",ans,l,r); } return 0; }