POJ2559 Largest Rectangle in a Histogram 题解 单调队列/单调栈 (直方图的最大矩形面积)

题目链接:http://poj.org/problem?id=2559

题目大意:
直方图中的每一个柱子都是一个宽度为 \(i\) 高度为 \(h_i\) 的矩形,求最大矩形面积。

解题思路:
定义两个数组:

  • \(L[i]\) 表示第 \(i\) 根柱子往左走碰到的第一根比它矮的柱子的坐标 \(+1\)(如果第 \(i\) 根柱子左边的柱子没有比它矮的,则 \(L[i] = 1\));
  • \(R[i]\) 表示第 \(i\) 根柱子往右走碰到的第一根比它矮的柱子的坐标 \(-1\)(如果第 \(i\) 根柱子右边的柱子没有比它矮的,则 \(R[i] = n\))。

然后从左到右遍历每个坐标,并且维护一个 \(h_i\) 单调递增的单调队列,则 \(i\) 入队列前,队尾元素对应的坐标就是 \(L[i]-1\)(若此时队列为空则 \(L[i]=1\))。

然后从右往左遍历每个坐标,并且维护一个 \(h_i\) 单调递增的单调队列,则 \(i\) 入队列前,队尾元素对应的坐标就是 \(R[i]+1\)(若此时队列为空则 \(R[i]=n\))。

实现代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <deque>
using namespace std;
const int maxn = 100010;
int n, L[maxn], R[maxn];
long long h[maxn], ans;
deque<int> que;
int main() {
    while (~scanf("%d", &n) && n) {
        for (int i = 1; i <= n; i ++) scanf("%lld", h+i);
        que.clear();
        for (int i = 1; i <= n; i ++) {
            while (!que.empty() && h[que.back()] >= h[i]) que.pop_back();
            if (!que.empty()) L[i] = que.back()+1;
            else L[i] = 1;
            que.push_back(i);
        }
        que.clear();
        for (int i = n; i >= 1; i --) {
            while (!que.empty() && h[que.back()] >= h[i]) que.pop_back();
            if (!que.empty()) R[i] = que.back()-1;
            else R[i] = n;
            que.push_back(i);
        }
        ans = 0;
        for (int i = 1; i <= n; i ++)
            ans = max(ans, (R[i]-L[i]+1) * h[i]);
        printf("%lld\n", ans);
    }
    return 0;
}
posted @ 2020-02-11 22:18  quanjun  阅读(152)  评论(0编辑  收藏  举报