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;
}