A-最大の長方形

トピック:

ヒストグラムに、ヒストグラムで最大の矩形領域を見つけます。例えば、左からヒストグラムにおける次の像高右それらが広い2、1、4、5、1、3、3、1であり、最大の矩形が遮光されます。
ここに画像を挿入説明

入力:

入力データの複数のセットを含みます。データの各セットは、整数nによって小さな長方形のヒストグラム表現され、あなたは1 <= N <= 100000次に、次のn個の整数はH1、...、Hnは、0 <= HI <= 1000000000これらを満足すると仮定することができます高さの各小矩形のデジタル表現を左から右にヒストグラムは、各小矩形の幅は1です。終了時に0に試験データ。

出力:

ライン毎にテストデータ出力は、整数回答を表します。

サンプル入力:

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

サンプル出力:

8
4000

トピック分析:

最低高さ部に矩形の幅、ヒストグラムの高さで矩形[L、R]被験者を必要としなければならない式前提高さの長方形の既知の面積に応じて、ヒストグラムの最大の矩形領域を必要とし、矩形の幅= L-R + 1。それほど重要な問題は、範囲として適切なL、Rを決定する方法です。

  • 最大の全体矩形、それはLにおけるRとして決定された最小の高さを作ります。

  • それは長方形の高さが決定された場合、同様に、左側エンドポイントは複数の左に、右右点、長方形の唯一の可能な最大の領域になければなりません。

  • 左側のエンドポイントは、高さ、それ左点の最初の少数のように決定されてもよいです。

  • なお、この第1の小高点数右の右端として決定することができます。

  • スタック要素スタック下単調にスタックからモノトーンスタック。

    •単調に増加するスタックを左に見つけることができます/右の最初の要素は、現在の要素よりも大きくなっています。
    •単調減少スタックを左に見つけることができる/右の最初の要素は、現在の要素よりも小さくなっています。
    それぞれ単調単調減少スタックを増加させ、スタックが各点で得られることは、エンドポイントの周りに高いです。

WA多数回、範囲内の高さデータ・タイプ、タイトルため0 <= HI <= 1000000000を、ではないがHI INTの範囲の範囲、しかしを超え得るとh(L-R + 1のプロセス内の領域に)バーストINT範囲を掛け、それは長い間、私が長いロングタイプに高さ及び面積を変換したロングタイプを変換する強い操作する必要がある、ワシントン州であろう。訓練された長い長い対応がLLDああ、忘れてはいけません(私はワシントン州、悲しいかなの追加を忘れてしまいました)

コード:

#include<iostream>
#include<stdio.h> 
#include<stack>
using namespace std;
const int maxn=1e5+100;
long long  L[maxn],R[maxn],w[maxn],a[maxn];
int n;
void solve()//找出各点右端点
{	
	stack<int> sa; 
	int l=1;int r=0;
	for(int i=1;i<=n;i++)
	{
		while(sa.size()>0 &&a[sa.top()]>a[i] )//单调递减栈找出右边第一个比当前元素小的元素
		{
			R[sa.top()]=i-1;
			sa.pop(); 
		} 
		sa.push(i);
	}
	while(sa.size()>0)//单调栈里的元素赋区间最右端点
	{
		R[sa.top()]=n;
		sa.pop();
	}
}
void solve1()//找出各点左端点
{	

	stack<int> sa; 
	int l=1;int r=0;
	//while(n--)
	for(int i=n;i>=1;i--)
	{
		while(sa.size()>0 &&a[sa.top()]>a[i] )//单调递减栈找出左边第一个比当前元素小的元素
		{
			L[sa.top()]=i+1;
			sa.pop(); 
		} 
		sa.push(i);
	}
	while(sa.size()>0)//单调栈里的元素赋区间最左端点
	{
		L[sa.top()]=1;
		sa.pop();
	}
}

int main()
{	
	//int n;//直方图小矩形个数 
	while(scanf("%d",&n)!=EOF)
	{
		if(n==0)
		{
			return 0;
		}	
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
		}
		solve(); 
		solve1();
		long long ans=0;
		for(int i=1;i<=n;i++)//计算面积
		{
			w[i]=a[i]*(R[i]-L[i]+1);
		}
		for(int i=1;i<=n;i++)//找出最大面积
		{
			if(w[i]>ans)
			{
				ans=w[i];
			}
		}
		printf("%lld\n",ans);
	} 
	return 0;	
} 
公開された21元の記事 ウォンの賞賛0 ビュー1096

おすすめ

転載: blog.csdn.net/qq_43746837/article/details/105012659