poj2559 Largest Rectangle in a Histogram(單調棧)
阿新 • • 發佈:2019-01-24
題意
有n個矩形,它們在一條水平線上且寬度都為1,長度分別為a[i]。求其中的最大子矩陣。
思考過程
我們從左往右列舉每一個矩形,第i個矩形依次嘗試寬度為1~n-i+1,記錄最低高度和最大面積。這個可以實現。
我們發現,其中的很多狀態是包含的,導致我們做了很多無用的嘗試。
事實上,對於一個相同的高度,我們希望它儘量寬,
題解
單調棧
建立一個單調遞增棧,因為一個高度低的潛力更大,所以我們把它壓到棧更深的地方。
對於一個大於棧頂的高度,我們直接放到棧頂上,記下這個位置。
如果小於棧頂,就要一直出棧直到大於棧頂的高度。彈出時計算一下以sta[top].h為高,以sta[top].p~i-1為寬的矩形的面積,看看要不要更新ans。
總結
藉助單調棧處理問題的思想在於及時排除不可能的選項,保持策略集合的高度有效性和秩序性,從而為決策提供更多條件和可能的方法。(引自《演算法進階》)
程式碼
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100010; int n; int a[maxn]; struct S { int h,p;//h高度 p位置 }sta[maxn];int top; int main() { while(scanf("%d",&n),n!=0) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); long long ans=0; top=0; for(int i=1;i<=n;i++) { int p=i; while(a[i]<=sta[top].h && top!=0) { ans=max(ans,(long long)sta[top].h*(i-sta[top].p));//計算矩形面積 p=sta[top].p;//p記錄最遠的位置 top--; } sta[++top]=(S){a[i],p}; } while(top!=0)//把所有留在棧內的矩陣計算一下 { ans=max(ans,(long long)sta[top].h*(n+1-sta[top].p)); top--; } printf("%lld\n",ans); } return 0; }