单调栈,顾名思义就是单调递增或者单调递减的栈。

在处理有些数据结构的问题的时候有妙用。

先看一下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;
}

 

posted on 2016-03-08 20:57  岳阳楼  阅读(189)  评论(0编辑  收藏  举报