給乙個直方圖,求直方圖中的最大矩形的面積。例如,下面這個中直方圖的高度從左到右分別是2, 1, 4, 5, 1, 3, 3, 他們的寬都是1,其中最大的矩形是陰影部分。
input
輸入包含多組資料。每組資料用乙個整數n來表示直方圖中小矩形的個數,你可以假定1 <= n <= 100000. 然後接下來n個整數h1, …, hn, 滿足 0 <= hi <= 1000000000. 這些數字表示直方圖中從左到右每個小矩形的高度,每個小矩形的寬度為1。 測試資料以0結尾。
output
對於每組測試資料輸出一行乙個整數表示答案。
sample input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0sample output
84000
將h1, …, hn存入陣列h[100001]。要求最大矩形面積,需要對每乙個h[i]求出以h[i]為高度的矩形的面積。h[i]高度已知,需要求出矩形的寬度,則需求出矩形的左邊界l和右邊界r的位置,即可通過公式寬度=r-l-1計算出寬度。對於h[i],左邊界為h中左邊數第乙個高度小於h[i]的元素下標+1,右邊界為h中右邊數第乙個高度小於h[i]的元素下標-1。面積s=h[i]*(r-l+1)。
對每乙個h[i],分別往左,往右迭代找出左右邊界,則時間複雜度為n²,會超時。
本題使用非增棧資料結構,只需要遍歷陣列h一次就可以找到每個h[i]的左/右邊界。設棧為st,棧儲存的資料型別為h[i]的下標i。記錄h[i]的左邊界為l[i],右邊界為r[i]。
右邊界的尋找方法:遍歷h,從左到右依次對單調棧st進行push(i)操作,若h[i]小於棧頂元素,則彈出棧頂元素,此時,i便為棧頂元素往右數第乙個小於棧頂元素的元素的下標。則棧頂元素st.top()的右邊界為i-1,將這個資訊記錄為r[st.top()]=i-1。就這樣push(i)到末尾,完成迭代後,若st內還存在元素,則這些元素的右邊界為陣列的末尾,即n,因此要把棧內剩餘元素全部彈出,並記錄下來r[st.top()]=n。此時遍歷完成,h內所有元素均入棧一次,出棧一次,並且其右邊界的下標被儲存在r中。左邊界與右邊界思路一致,只是掉轉了遍歷的方向。使用上述方法,複雜度為n。
注意高度h的取值範圍,需要使用long long int 來儲存高度和面積,否則會出錯。
#include
#include
using
namespace std;
long
long
int h[
100010
],ans,s;
int n,l[
100001
],r[
100001];
inline
long
long
intmax
(long
long
int a,
long
long
int b)
stack<
int> st;
intmain()
for(
int i=
1;i<=n;i++
) st.
push
(i);
}while
(!st.
empty()
)for
(int i=n;i>=
1;i--
) st.
push
(i);
}while
(!st.
empty()
)for
(int i=
1;i<=n;i++
)printf
("%lld\n"
,ans);}
return0;
}
第五周周總結
時間進度表 日期開始時間 結束時間 中斷時間 淨時活動 備註3月15日 7 10 9 10 120打程式 規範 進行初步構思 3月16日 7 10 9 10 120打程式 實現減法無負數 3月17日 8 00 10 00 120打程式 實現減法無負數 3月18日 4 10 5 50 5 00 5 1...
第五周周記
第五周周記 本週完成了 1.html的網頁設計作業,學習了標籤 用 製作網頁 製作表單站點等。2.學習了資料結構的順序表和鏈式表的動態儲存和應用,以及如何寫 3.學習了ps 選單的部分功能。4.學會了繪製一張網路拓撲圖。希望能夠更加努力,收穫成長。週數專業學習目標 專業學習時間 新增 量 部落格發表...
第五周作業
includeusing namespace std class student 用引數的初始化表對資料成員初始化。void max student arr void display private int num int score void student display void studen...