第五周作业 A题

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

解题思路:

我们要找到,左右两边最后一个比a[i]大的位置,R和L,然后以它作为高,R-L+1作为他的宽,计算出矩形面积
1.寻找R
若要找右边最后一个比他大的位置,则,我们找到右边第一个比它小的位置-1,就能得到
我们利用单调栈来解决,当我们往栈内插入数值时,若栈顶元素>待插入元素
这时我们就要pop掉栈顶的元素维护单调,那么此时的栈顶元素就是第一个比他小的元素位置,-1则就是最后一个比他大的位置
当我们都插入完成,并且栈不为空的话,则表示留在栈内的元素,在其右侧没有比他小的元素,它可以扩展到n
2.寻找L
与R同理,将数组从n开始遍历到1,但与R不同的是,如果我们向左找到了第一个比它小的位置,求最后一个比她大的位置时是==+1==(左右分清)
而且当栈不为空时,说明他的左边没有比他大的,则,栈内的元素不能扩展,赋值1
接下来就比较简单啦,只需要不停的求出面积,算出最大就好了(这里还有一个要注意的地方,就是面积的计算有可能会超 所以要把ans定义成long long形式,计算的时候也要转换

#include<iostream>
#include<stdio.h>
using namespace std;
const int N=100010; 
int n,a[N],R[N],L[N],st[N];
void solveR()
{
 int l=1, r=0;
 for(int i=1;i<=n;i++)
 {
  while(l<=r && a[st[r]] > a[i])
  {
   R[st[r]] = i-1;
   r--;
  }
  st[++r] = i;
 }
 while(r>=0)
 {
  R[st[r]]=n;
  r--;
 }
}
void solveL()
{
  int l=1, r=0;
 for(int i=n;i>=1;i--)
 {
  while(l<=r && a[st[r]] > a[i])
  {
   L[st[r]] = i+1;
   r--;
  }
  st[++r] = i;
 }
 while(r>=0)
 {
  L[st[r]]=1;
  r--;
 }
 } 
int main()
{
 cin>>n;
 while(n!=0)
 {
  for(int i=1;i<=n;i++) scanf("%d",&a[i]);
  solveR();
  solveL();
//  for(int i=1;i<=n;i++)
//  cout<<R[i]<<" ";
//  cout<<endl;
//  for(int i=1;i<=n;i++)
//  cout<<L[i]<<" ";
  long long ans=0;
  for(int i=1;i<=n;i++)
  {
   if(ans<(long long)a[i]*(R[i]-L[i]+1))
    ans=(long long)a[i]*(R[i]-L[i]+1);
  }
  cout<<ans<<endl;
  cin>>n;
 }
 return 0;
 } 
发布了19 篇原创文章 · 获赞 0 · 访问量 227

猜你喜欢

转载自blog.csdn.net/GuaXX/article/details/105046297