HDU 1506 解题报告 (单调栈)

    看题传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1506

题意比较明显,就是找以某一个矩形为高的最大的矩形。这个题可以用单调栈来求解,需要注意的是如果从左到右再从右到左两次循环的话容易TLE,其实只要从左到右一次循环就能出答案。这题可以用模拟栈,也可以用STL,其实都差不多……

先介绍一下简单说一下单调栈。所谓单调,就是保持栈中的元素保持一个严格或非严格的递增或递减序列,单调栈可以方便的用来找出某个元素左边或右边第一个比他小或者比他大的元素。 

具体过程就是:首先判断栈是否为空,若栈空,则直接压入栈中,否则判断栈顶元素与待处理元素的大小关系,根据需要选择将待处理压入或者将栈顶元素弹出,然后从头开始再次执行,直到所有元素处理完毕。

在这个题目当中呢,实际上要求的是以每个柱的高度为矩形的最高高度,向左右延伸以求得最大面积,那么就需要找到每个元素左边第一个和右边第一个比它大的元素。正如前面提到的,如果循环两边的话容易超时,所以要在一次循环中得出。

开辟两个数组,l 和 r,分别保存每个元素左边第一个和右边第一个比它小的元素的下标,一开始全部初始化为自己的下标,表示没找到。然后将元素依次压入栈中,压入的时候,若栈非空且元素大于栈顶元素,将 l[i] 保存为栈顶元素的位置,再将元素下标压入栈中。当这一元素弹出时,r[i] 记录下使其弹出的这一元素的下标。最后就是计算了。

 

最后要注意:1. 要使用long long保存答案,否则会丢失精度。     2.  如果是用的STL栈,要记得清空栈

下面上一波C艹实现~~~

#include <cstdio>
#include <stack>
#include <algorithm>
using namespace std;
const int MAXN = 100010;
typedef long long LL;
stack<LL> sta;
LL input[MAXN];
LL left[MAXN], right[MAXN];
int main()
{
    //freopen("input.txt", "r", stdin);
    LL n;
    while(~scanf("%lld", &n) && n){
        for(int i = 0;i < n;++i){
            scanf("%lld",&input[i]);
        }

        input[n] = -1;
        for(int i = 0;i <= n;++i){
            left[i] = right[i] = i;
            while(!sta.empty() && input[i] < input[sta.top()] ){
                left[i] = left[sta.top()];
                right[sta.top()] = i - 1;
                sta.pop();
            }
            if(!sta.empty() && input[i] == input[sta.top()] ) 
                left[i] = left[sta.top()];  //这里等于要特判一下,不用弹出栈顶。
            sta.push(i); 
        }

        LL ans = 0;
        for(int i = 0;i < n;++i){
            ans = max(ans, (right[i] - left[i] + 1) * input[i] );
        }
        printf("%lld\n",ans);
        while(!sta.empty())
            sta.pop();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/aldo101/article/details/81086800