1. 程式人生 > >HDU1506 Largest Rectangle in a Histogram(算競進階習題)

HDU1506 Largest Rectangle in a Histogram(算競進階習題)

面積 習題 inf 所有 getchar 需要 def 因此 最大

單調棧裸體

如果矩形高度從左到右是依次遞增,那我們枚舉每個矩形高度,寬度拉到最優,計算最大面積即可

當有某個矩形比前一個矩形要矮的時候,這塊面積的高度就不能大於他本身,所以之前的所有高於他的矩形多出來的部分都沒用了,不會再計算第二次。

因此我們只需要用單調棧維護矩形高度即可,當有高度較低的矩形進棧時,先將之前比他高的每個矩形彈出,寬度累加,更新答案。然後我們要進棧的矩形的寬度也要變成之前累加的寬度+1,因為要保留有用部分。。

有個小技巧:為了方便程序,在末尾加一個高度為0的矩形

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int X = 0, w = 0; char ch = 0;
    while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C yql){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % yql)if(p & 1)ans = 1LL * x * ans % yql;
    return ans;
}
ll h[100005], s[100005], w[100005], tot;
int main(){

    int n;
    while(cin >> n && n){
        memset(h, 0, sizeof h);
        memset(s, 0, sizeof s);
        memset(w, 0, sizeof w);
        ll ans = 0; w[n + 1] = 0; tot = 0;
        for(int i = 1; i <= n; i ++) cin >> h[i];
        for(int i = 1; i <= n + 1; i ++){
            if(s[tot] > h[i]){
                ll width = 0;
                while(tot > 0 && s[tot] > h[i]){
                    width += w[tot];
                    ans = max(ans, (ll)width * s[tot]);
                    tot --;
                }
                s[++tot] = h[i], w[tot] = width + 1;
            }
            else{
                s[++tot] = h[i], w[tot] = 1;
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

HDU1506 Largest Rectangle in a Histogram(算競進階習題)