1. 程式人生 > >POJ2559 Largest Rectangle in a Histogram 單調隊列

POJ2559 Largest Rectangle in a Histogram 單調隊列

sta eight 所有 for 我們 return rec += std

題目大意

  有一個直方圖,其所有矩形的底均是1(以後簡稱小矩形)。給出這些矩形的高度,求這些矩形的並集中存在的面積最大的矩形(簡稱大矩形)的面積。

題解

  大矩形的高必然一邊等於一個小矩形的高,另一邊小於等於另一個小矩形的高。

  我們現考慮面積最大矩形左邊高等於其所在小矩形的高的情況,則其右邊高小於等於其對應的小矩形的高(以後將此簡稱為左等高矩形)。我們要維護一個單調棧,使得棧裏的矩形的高度都是單調遞增的。一個一個枚舉小矩形,如果當前小矩形高度比棧頂的矩形高度高或等,則如果所求大矩形是個左邊為棧內矩形的左等高矩形,則這條小矩形就必然位於這個大矩形的右邊所在小矩形的位置及左側(性質1)(因為寬度越寬越好)。將此小矩形推入棧中。此情況一直延續到當前小矩形比站定的矩形高度低時。此時如果把此小矩形推入棧內,棧就不滿足性質1了。因此這時便是開始利用性質1結算(當前小矩形左方的)左等高矩形的時刻了(小矩形高度乘以到當前小矩形的寬度)。

  那麽右等高矩形呢?右等高矩形相當於將該大矩形以上部分的小矩形削掉以後的左等高矩形。因此當遇到上述的第二種情況時,當棧頂矩形高度小於當前小矩形高度時,退出,然後將寬度為累加值,高度為當前小矩形高度的矩形推入棧內即可。註意最後要增加一個高度為0的小矩形,來應對大矩形右邊為最右一個小矩形的情況。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;

const int MAX_N = 100010;
int A[MAX_N];

struct Rect
{
	int Height, Width;
	
	Rect(int height, int width):Height(height),Width(width){}
};
stack<Rect> St;

int main()
{
	int n;
	while (scanf("%d", &n) && n)
	{
		for (int i = 1; i <= n; i++)
			scanf("%d", A + i);
		long long ans = 0;
		A[++n] = 0;
		St.push(Rect(A[1], 1));
		for (int i = 2; i <= n; i++)
		{
			if (A[i] >= St.top().Height)
				St.push(Rect(A[i], 1));
			else
			{
				long long width = 0;
				while (!St.empty() && St.top().Height >= A[i])
				{
					ans = max(ans, (long long)St.top().Height * (width+=St.top().Width));
					St.pop();
				}
				St.push(Rect(A[i], width + 1));
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}

  

POJ2559 Largest Rectangle in a Histogram 單調隊列