目录
》题目《
在X轴上水平放置着 N 个条形图,这 N 个条形图就组成了一个柱状图,每个条形图都是一个矩形,每个矩形都有相同的宽度,均为1单位长度,但是它们的高度并不相同。例如下图,图1包含的矩形的高分别为2,1,4,5,1,3,3 单位长度,矩形的宽为1单位长度。
你的任务就是计算柱状图中以X轴为底边的最大矩形的面积。图2阴影部分就是上述例子的最大矩形面积
》输入《
输入数据的第一行是一个整数 N(1≤ N ≤100000),表示柱状图包含 N 个矩形。紧接着 N 个整数h1,...,hn(0≤ hi ≤20000, 1≤ i≤ N),表示柱状图中按从左到右顺序给出的矩形的高度。矩形的宽度为1。
》输出《
最大矩形的面积
》样例输入《
7
2 1 4 5 1 3 3
》样例输出《
8
》思路《
大多数读者一眼就看出了这是最大矩形,怎么搞?怎么搞?
首先,我们思考一下每个矩形是如何来的
是不是以每栋建筑的高度为矩形的一边,再寻找另一边的长度(是的)
如何寻找另一边呢?
是不是左边第一个比这个建筑低的位置(左边界)到右边第一个比这个建筑低的位置 (右边界)之间的距离(翻回去看,是不是?)
如何搞?
单调队列就很有用了。
首先,如果这个元素要入队(必须进去,别问我为什么),就要维护此队列的单调性(从栈底到栈顶(非)递增(减))
这道题就要用递增序列了(为什么后面会讲)
怎么求左边界呢?
试想:h[i-1] > h[i],是不是以 h[i-1] 为一边的矩形的右边界已经确定(因为已经不可能再往右延伸了嘛)
那么以 h[i] 为一边的矩形的左边界就要向左移一位(即 h[i] 的右边界更新成 i-1)
而这时 h[i-1] 已经已经没用了,所以我们就可以计算以 h[i-1] 为一边的矩形的面积,而它的右边界是不是就是 h[i] 的位置?
以它为一边的矩形的面积是不是就是 (h[i]的位置 - h[i-1]的位置)*h[i]。
所以,每当后一个建筑的高度小于前一个的高度时,就要把前一个建筑弹出去,更新位置(是不是单调递增的?)
至于细节嘛,自己想(cuo)去吧
》代码《
#include <stack>
#include <cstdio>
#include <iostream>
using namespace std;
struct node{
int p, zhi;
}a[100005], b;
stack<node> t;
int ans, n;
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i ++){
scanf("%d", &a[i].zhi);
a[i].p = i;
}
t.push(a[1]);
for(int i = 2; i <= n; i ++){
int pp = a[i].p;
while( !t.empty() && t.top().zhi > a[i].zhi ){
b = t.top();
t.pop();
a[i].p = b.p;
int big = (pp - b.p) * b.zhi;
ans = max(big ,ans);
}
t.push(a[i]);
}
while( !t.empty() ){
b = t.top();
t.pop();
int big = (n + 1 - b.p) * b.zhi;
ans = max(big ,ans);
}
printf("%d\n",ans);
return 0;
}
欢迎读者补充与交流