题目链接: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
", ans);
}
return 0;
}