タイトル:
ヒストグラムを指定して、ヒストグラムの最大の長方形の領域を見つけます。たとえば、下の図のヒストグラムの高さは左から右に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;
}