1. 程式人生 > 其它 >Largest Rectangle (單調棧,同POJ2559)

Largest Rectangle (單調棧,同POJ2559)

技術標籤:思維單調棧

題目連結

題意:
題意:給你寬度為一,高度不同的n個矩形,讓求出一個最大面積的矩形。
如下圖所示
在這裡插入圖片描述

分析:
方法一:
根據題意可知,若以h為起點,分別往兩邊找比h矮的矩形,此時比h矮的前一個組成的矩形便是能圍成的最大面積;
上述有一些意識流,看程式碼比較好理解

#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include
<map>
#include <set> #include <cstring> #include <stack> #include <string> using namespace std; typedef long long ll; const int N = 1e5+199; const double Pi = acos(-1); ll h[N]; int l_min[N],r_min[N]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt"
,"r",stdin); #endif // ONLINE_JUDGE int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lld",&h[i]); l_min[i]=r_min[i]=i; } h[0]=h[n+1]=-1; for(int i=1;i<=n;i++){//看似是n^2的複雜度,其實是O(n),有點KMP的意思 int j=i-1; while
(h[j]>=h[i])//找i的左邊比自己第一個矮的位置 j=l_min[j]-1;//這一步很重要,可以快速收斂,這樣就不是n^2的複雜度了 l_min[i]=j+1; } for(int i=n;i>=1;i--){ int j=i+1; while(h[j]>=h[i])//找i的右邊比自己第一個矮的位置 j=r_min[j]+1; r_min[i]=j-1; } ll ans=0; for(int i=1;i<=n;i++){ ans=max(ans,(ll)(r_min[i]-l_min[i]+1)*h[i]); } printf("%lld\n",ans); return 0; }

方法二:單調棧

我們用棧來維護一個單調遞增的矩形高度,如果遇到一個大於等於棧頂的元素,便將其入棧,否則彈出,然後計算,直到棧頂元素小於當前的元素才再次入棧;
同樣有點意識流,還是看程式碼,最後能手動模擬一下;

#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cstring>
#include <stack>
#include <string>
using namespace std;

typedef long long ll;
const int N = 1e5+199;
const double Pi = acos(-1);
ll h[N];
int main()
{

//    #ifndef ONLINE_JUDGE
//    freopen("in.txt","r",stdin);
//    #endif // ONLINE_JUDGE
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lld",&h[i]);
    }
    h[n]=-1;//這是要用到單調棧必不可少的

    int pos=0;
    ll ans=0,maxval=0;
    stack<int>s;//用棧來儲存下標
    while(pos<=n){
        if(s.empty() || h[pos]>=h[s.top()])
            s.push(pos);
        else{
            int k;
            while(!s.empty() && h[pos]<h[s.top()]){
                k=s.top();
                s.pop();
                ans=max(ans,h[k]*(pos-k));
            }
            h[k]=h[pos];//這個地方需要好好理解
            s.push(k);
        }
        pos++;
    }
    printf("%lld\n",ans);
    return 0;
}