1. 程式人生 > >HDU-1506 單調棧

HDU-1506 單調棧

直方圖是由在共同基線上排列的矩形序列組成的多邊形。矩形具有相等的寬度,但可以具有不同的高度。例如,左邊的圖顯示了由高度為2, 1, 4、5, 1, 3、3的矩形組成的直方圖,其中單位為矩形的寬度為1: 

通常,直方圖用於表示離散分佈,例如文字中字元的頻率。請注意,矩形的順序,即它們的高度,是重要的。在直方圖中計算最大矩形的面積,該直方圖也是在公共基線上對齊的。右邊的圖形顯示了直方圖中最大的對齊矩形。

Input

多組測試資料 每組測試資料的第一行為n(1 <= n <= 100000), 表示圖形有n個小矩形構成. 接下來一行輸入n個整數h1, h2...hn (0 <= hi <= 1000000000, 1 <= i <= n), 表示每個小矩形的高度 n為0時程式結束

Output

僅輸出一行表示面積的最大值

Sample Input

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

Sample Output

8
4000

 要求最大的矩形的面積.想一想可以得到最大面積就是從某一個矩形向兩邊擴充套件, 擴充套件的條件是左邊或者右邊的高度大於等於當前位置的高度. 這樣就可以得到最大的面積

 單調棧實現

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<string>
#include<stack>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 100000 + 100;
ll a[MAXN];
int L[MAXN], R[MAXN];
int main(){
	int n;
	while (scanf("%d", &n) != EOF && n){
		stack<int> s; s.push(0);
		ll ans = 0;
		for (int i = 1; i <= n + 1; i++){
			if (i <= n) scanf("%lld", &a[i]);
			else a[i] = 0;
			L[i] = R[i] = i;
			while (s.size() > 1 && a[s.top()] >= a[i]){//保證棧頂元素的下邊沒有大於自己的
				//如果a[棧頂元素] >= a[當前元素], 那麼棧頂元素右邊的第一個小於自己的就是這個元素
				R[s.top()] = i - 1;
				s.pop();
			}//迴圈保證有一個左邊界
			L[i] = s.top();
			s.push(i);
		}
		for (int i = 1; i <= n; i++) ans = max(ans, (R[i] - L[i])*a[i]);
		printf("%lld\n", ans);
	}
#ifdef __wh
	system("pause");
#endif
	return 0;
}
//6 2 5 2 5 5 2