zoukankan      html  css  js  c++  java
  • Week5 作业 A

    题目描述:

    给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是2, 1, 4, 5, 1, 3, 3, 他们的宽都是1,其中最大的矩形是阴影部分

     思路:

    对于第i个矩形,以其高度h[i]能组成的最大矩形是通过如下方式求的:找出i左边第一个高度小于h[i]的,和i右边第一个高度大于h[i]的,用长度乘以h[i]就是了。对于每一个矩形进行这样的操作,找出其中的最大值就行了。

    找的过程可以用单调栈来解决,这里以找右边界R[i]为例:从1到n进行遍历,维护一个单调栈(从栈底到栈顶递增),当进入的元素a[i]大于等于栈顶元素时,进栈,否则弹出栈顶元素x,同时说明x的最右边界就是i-1,然后继续判断栈顶元素,直到栈顶元素小于等于a[i],然后把i进栈,继续向后搜索;

    所有元素都搜索完毕后,可能有一部分的R[i]==0,说明这些元素的右边界没确定,也就是说,从i到n一直在递增;这些元素一定都还在栈中,处理一下即可。

    找出每个i的左右边界之后,取 h[i]*(R[i]-L[i]) 的最大值即可。

    代码:

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <stack>
     4 #include <cstring>
     5 using namespace std;
     6 const int MAXN=1e5+5;
     7 typedef long long ll;
     8 stack<int> S;
     9 ll a[MAXN],ans;
    10 int R[MAXN],L[MAXN];  //R[i]=k表示a[i]右边的边界是k,其元素是a[k] 
    11 int main()
    12 {
    13     int n;
    14     while( scanf("%d",&n) && n!=0 )
    15     {
    16         memset( a,0,sizeof(a) );
    17         memset( R,0,sizeof(R) );
    18         memset( L,0,sizeof(L) );
    19         ans=0;
    20         for(int i=1;i<=n;i++)
    21         {
    22             scanf("%d",a+i);
    23             while( !S.empty() && a[ S.top() ]>a[i] )
    24             {
    25                 R[ S.top() ] =i-1;             //如果遇到连续递增的,则其R[i]=0;否则一定R[i]!=0; 
    26                 S.pop();
    27             }
    28             S.push(i);
    29         }
    30         while( !S.empty() )    //如果栈中还有元素则说明其R[i]=0;
    31         {
    32             R[ S.top() ]=n;
    33             S.pop();
    34         } 
    35         for(int i=n;i>=1;i--)
    36         {
    37             while( !S.empty() && a[ S.top() ]>a[i] )
    38             {
    39                 L[ S.top() ] =i+1;             //如果遇到连续递增的,则其L[i]=0;否则一定L[i]!=0; 
    40                 S.pop();
    41             }
    42             S.push( i );     
    43         }
    44         while( !S.empty() )    //如果栈中还有元素则说明其L[i]=0;
    45         {
    46             L[ S.top() ]=1;
    47             S.pop();
    48         } 
    49         for(int i=1;i<=n;i++)
    50         {
    51             ll tmp=a[i]*(R[i]-L[i]+1);
    52             ans=max( ans,tmp );
    53         }
    54         cout<<ans<<endl;
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    Cygwin一些设置总结!
    【补题】牛客58矩阵消除【数据水的一匹,算法:二进制枚举】
    【补题】牛客58E题(数学)
    [补题]牛客练习56,迷宫【orz】
    【补题】牛客58E题(数学)
    判断两个二叉树是否相同
    判断两个二叉树是否相同
    利用费马小定理求逆元
    [补题]牛客练习56,迷宫【orz】
    【补题】牛客58矩阵消除【数据水的一匹,算法:二进制枚举】
  • 原文地址:https://www.cnblogs.com/qingoba/p/12548921.html
Copyright © 2011-2022 走看看