WEEK 5最大の長方形

タイトル:

ヒストグラムを指定して、ヒストグラムの最大の長方形の領域を見つけます。たとえば、下の図のヒストグラムの高さは左から右に2、1、4、5、1、3、3で、幅は1で、最大の長方形は網掛け部分です。
ここに画像の説明を挿入

入力:

入力に複数のデータセットが含まれています。各データセットは整数nを使用して、ヒストグラム内の小さな四角形の数を表します。1<= n <= 100000と想定できます。次に、次のn個の整数h1、…、hnは0 <= hi <= 1000000000を満たします。数値は、ヒストグラムの左から右への各小さな長方形の高さを示し、各小さな長方形の幅は1です。テストデータは0で終わります。

出力:

テストデータの各セットについて、答えを示す整数が1行に出力されます。

入力例:

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

出力例:

8
4000

アイデア:

現在の高さa [i]から左右に広がり、到達可能な左端の点がl、右端の点がrであるとすると、この点の最大の長方形の領域は[i] *(r-l + 1);になります。問題の意味は、左境界lがa [j-1] <a [i]を満たす最大のjであることです。つまり、点iから左に移動するiよりも小さい高さの最初の点の右側の点、および右境界r [j + 1] <a [i]を満たす最小のjです。つまり、点iから右に、最初の点の1つ左に、高さi未満で移動します。したがって、単調スタックの性質を使用して、特定のポイントを継続的に取得できます。つまり、高さの最大面積の長方形の左側と右側の境界を決定できます。

コード:

#include <iostream>
#include <stack>
#include <algorithm>

using namespace std;

stack<int> s;
const int N = 1e6+10;
long long n, ans;
long long a[N], R[N], L[N];

void solvel()
{
	while (s.size() != 0)
		s.pop();
	for (int i = 1; i <= n; i++)
	{
		while (s.size() != 0 && a[s.top()] >= a[i])
			s.pop();
		if (s.empty())
			L[i] = 1;
		else
			L[i] = s.top() + 1;
		s.push(i);
	}
}

void solver()
{
	while (s.size() != 0)
		s.pop();
	for (int i = n; i >= 1; i--)
	{
		while (s.size() != 0 && a[s.top()] >= a[i])
			s.pop();
		if (s.empty())
			R[i] = n;
		else
			R[i] = s.top() - 1;
		s.push(i);
	}
}

int main()
{
	while (scanf_s("%d",&n)!=EOF)
	{
		if (n == 0)
			break;
		ans = 0;
		for (int i = 1; i <= n; i++)
			scanf_s("%d", &a[i]);
		solver();
		solvel();
		for (int i = 1; i <= n; i++)
			ans = max(ans, a[i] * (R[i] - L[i] + 1));
		cout << ans << endl;
	}
    return 0; 
}
元の記事を32件公開しました Likes0 訪問数685

おすすめ

転載: blog.csdn.net/qq_43814559/article/details/105000595