HDU - 1506 直方图

直方图是由在共同基线上排列的矩形序列组成的多边形。矩形具有相等的宽度,但可以具有不同的高度。例如,左边的图显示了由高度为2, 1, 4、5, 1, 3、3的矩形组成的直方图,其中单位为矩形的宽度为1:

通常,直方图用于表示离散分布,例如文本中字符的频率。请注意,矩形的顺序,即它们的高度,是重要的。在直方图中计算最大矩形的面积,该直方图也是在公共基线上对齐的。右边的图形显示了直方图中最大的对齐矩形。
Input
多组测试数据 每组测试数据的第一行为n(1 <= n <= 100000), 表示图形有n个小矩形构成. 接下来一行输入n个整数h1, h2…hn (0 <= hi <= 1000000000, 1 <= i <= n), 表示每个小矩形的高度 n为0时程序结束
Output
仅输出一行表示面积的最大值
Sample Input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
Sample Output
8
4000

题目没法直接暴力,最开始以为是用尺取法来维护,发现自己总是无法扫描的最后,
看了一下题解发现是使用单调栈。
就是维护一个从小到大的栈。获取两个信息,对于每个节点获取以它为高的最大左边界和最大右边界,然后扫描一遍就可以了。

代码如下:

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<cstdio>

using namespace std;
const int MAX = 100010;
typedef long long ll;
#define rep(n) for(int i=1;i<=n;++i)
#define Rrep(n) for(int i=n;i>=1;--i)
ll h[MAX];
int L[MAX], R[MAX];//左右最大边界
int main(void) {
    int N;
    while (scanf("%d", &N) && N) {
        rep(N) {
            scanf("%lld", &h[i]);
        }
        stack<int> st;
        rep(N) {
            while (!st.empty() && h[st.top()] >= h[i])//如果栈里面比他大.
                st.pop();
            if (st.empty())
                L[i] = 1;//栈为空表示前面的都比他高,所以为最左边界
            else
                L[i] = st.top() + 1;
            st.push(i);
        }
        while (!st.empty()) st.pop();
        //同理获取最大右边界
        Rrep(N) {
            while (!st.empty() && h[st.top()] >= h[i])
                st.pop();
            if (st.empty())
                R[i] = N;
            else
                R[i] = st.top() - 1;
            st.push(i);
        }
        ll res = 0;
        rep(N) {
            res = max(res, h[i] * (R[i] - L[i]+1));
        }
        printf("%lld\n", res);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhao5502169/article/details/80085209
今日推荐