1. 程式人生 > >POJ 2559 &&HDU 1506 Largest Rectangle in a Histogram && 51nod 1102 面積最大的矩形 單調棧的應用

POJ 2559 &&HDU 1506 Largest Rectangle in a Histogram && 51nod 1102 面積最大的矩形 單調棧的應用


題目大意POJ 2559 &&HDU 1506 && 51NOD 1102這三個題其實都是一個題,有N個矩形,寬度都為1,給出N個矩形的高度,求由這N個矩形組成的圖形包含的最大的矩形面積。

Sample Input

7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0

Sample Output

8
4000

思路:對於每個矩形,我們求出它向左向右分別能延伸的長度,然後乘以它的高度,這就是以當前矩形為最低高度可以得到的最大的面積。只需要求個最大值即可。總結性的來說就是:給定一序列,尋找某一子序列,使得子序列中的最小值乘以子序列的長度最大。這是單調棧的一種應用。

具體實現:構造一個單調遞減的單調棧,如果棧為空或入棧元素大於等於棧頂元素則入棧,否則會破壞棧的單調性,將大於入棧元素的棧頂元素出棧,直到棧為空或遇到一個小於等於入棧元素的元素。然後將最後一次出棧的棧頂元素向左向右延伸,也就是確定以棧頂元素的高度為最低高度的矩形的寬度,改變其對應的值,然後入棧。

並且將陣列最後一個元素設為最小值,以最後清空棧內所有元素。

注意

1.單調棧儲存的是每個矩形的編號,也就是位置。

2.在維護單調棧,也就是每個矩形向左向右延伸的過程中會使原來陣列的值改變。

3.資料很大,要用long long型。

4.最後一次出棧的棧頂元素就是當前入棧元素可以向左拓展到的最大距離。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stack>
using namespace std;
typedef long long LL;

int main()
{
	int i,n,top; //top指向棧頂 
	stack<int> st; //棧用於儲存矩形的編號,即位置 
	LL tmp,ans,a[100010]; //tmp為臨時變數,記錄面積的值,ans為結果,記錄最大面積值 
	while(~scanf("%d",&n)&&n)
	{
		for(i=0;i<n;i++)
			scanf("%lld",&a[i]);
		ans=0;
		a[n]=-1; //最後一個元素設為最小值,以最後清空棧 
		for(i=0;i<=n;i++)
		{
			if(st.empty()||a[i]>=a[st.top()])
			{ //如果棧為空或入棧元素大於等於棧頂元素 ,則入棧 
				st.push(i);
			}
			else
			{
				while(!st.empty()&&a[i]<a[st.top()])
				{ //如果棧非空且入棧元素小於棧頂元素,則將棧頂元素出棧 
					top=st.top();
					st.pop();
					tmp=(i-top)*a[top]; //在出棧過程中計算面積值 
					if(tmp>ans) ans=tmp; //更新面積最大值 
				}
				st.push(top); //只將可以延伸到的最左端的位置入棧
				a[top]=a[i];  //並修改該位置的值 
			}			
		}
		printf("%lld\n",ans);
	}
	return 0;
}