A - 最大矩形
题目描述
给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是2, 1, 4, 5, 1, 3, 3, 他们的宽都是1,其中最大的矩形是阴影部分。
Input
输入包含多组数据。每组数据用一个整数n来表示直方图中小矩形的个数,你可以假定1 <= n <= 100000. 然后接下来n个整数h1, …, hn, 满足 0 <= hi <= 1000000000. 这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1。 测试数据以0结尾。
Output
对于每组测试数据输出一行一个整数表示答案。
Sample Input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
Sample Output
8
4000
题解
- 采用单调递减栈的思想。
- 数组h存放输入的各小矩形的高度,数组R表示小矩形右边第一个比他矮的矩形的下标,数组L表示小矩形左边第一个比他矮的矩形的下标,stack用来表示栈。
- 循环n次,每次都把当前h[i]的下标i压入栈中,压栈时,因为要为维持单调递减栈,所以要把i前面比他高的都弹出栈。弹栈时,要弹出来的元素stack[r]的右边第一个比它小的元素即为当前要压入的元素(因为比它大的元素入栈时不会将它弹出,只有第一个比它小的会将它弹出),所以R[stack[r]]=i,左边第一个比它小的元素即为栈中它的前一个元素(因为比它大的元素在它入栈时都被弹出了),所以L[stack[r]]=stack[r-1]。弹栈完成后(栈为空或栈顶元素比要压入元素小),将i压入栈中。
- 将所有元素都压入栈中后,弹出栈中剩下的元素(右边界为n,左边界为栈中它的前一个)。然后计算每个i对应的大矩形的面积,找出最大值并输出。
坑点
注意数据大小,long long 。
代码
#include <iostream>
#include <stdio.h>
using namespace std;
long long h[100100];
int stack[100100],R[100100],L[100100];
//stack存放的是对应的h下标
int main(int argc, char** argv) {
int n;
while(1){
scanf("%d",&n);
if(n==0){break;}
for(int i=0;i<n;i++){
scanf("%lld",&h[i]);
}
int l=1,r=0;//从栈顶到栈底递减
stack[0]=-1;
for(int i=0;i<n;i++){
while(r>=l&&h[i]<h[stack[r]]){//需要弹栈
R[stack[r]]=i;
L[stack[r]]=stack[r-1];
r--;
}
//入栈
r++;
stack[r]=i;
}
while(r>=l){//弹出栈中剩下的
R[stack[r]]=n;
L[stack[r]]= stack[r-1];
r--;
}
//计算最大矩形
long long area=0;
for(int i=0;i<n;i++){
long long tmp=h[i]*(R[i]-L[i]-1);
if(tmp>area){
area=tmp;
}
}
printf("%lld\n",area);
}
return 0;
}