CCF 最大的矩形
問題描述
| 試題編號: | 3 |
| 試題名稱: | 最大的矩形 |
| 時間限制: | 1.0s |
| 內存限制: | 256.0MB |
| 問題描述: |
問題描述
在橫軸上放了n個相鄰的矩形,每個矩形的寬度是1,而第i(1 ≤ i ≤ n)個矩形的高度是hi。這n個矩形構成了一個直方圖。例如,下圖中六個矩形的高度就分別是3, 1, 6, 5, 2, 3。 請找出能放在給定直方圖里面積最大的矩形,它的邊要與坐標軸平行。對于上面給出的例子,最大矩形如下圖所示的陰影部分,面積是10。 輸入格式
第一行包含一個整數n,即矩形的數量(1 ≤ n ≤ 1000)。 第二行包含n 個整數h1, h2, … , hn,相鄰的數之間由空格分隔。(1 ≤ hi ≤ 10000)。hi是第i個矩形的高度。 輸出格式
輸出一行,包含一個整數,即給定直方圖內的最大矩形的面積。
樣例輸入
6 3 1 6 5 2 3 樣例輸出
10
|
之前用O(n^2)寫的沒有得滿分,學了下O(n)的做法。
題意找出最大面積的長方形。
之前做過類似的題,有O(n)復雜度的做法,用棧維護一個遞增的序列,棧中存對應高度的位置。
每遍歷一個元素,判斷是否是棧中最大的元素,如果不是,把棧頂的元素彈出,并計算以棧頂元素為最大值高度時的長方形面積。
面積的長度為棧頂元素之前的一個元素到當前遍歷的元素的之間的長度,邊界情況特殊考慮。
注意彈棧是每一次都要判斷,比如34555下標01234,如果有等號的時候到3,2彈棧,但是1,0不彈棧。
#include <cstdio>
#include <iostream>
#include <stack>
#include <cstring>
using namespace std;
stack<int> s;
int main()
{
int n,data[];
while(scanf("%d",&n)!=EOF)
{
memset(data,,sizeof(data));
for(int i=;i<n;i++)
scanf("%d",&data[i]);
int mx=;
for(int i=;i<n;i++)
{
if(s.empty()) s.push(i);
else
{
while(!s.empty()&&data[i]<data[s.top()])
//注意彈棧是每一次都要判斷,
//比如34555下標01234,如果有等號的時候到3,2彈棧,但是1,0不彈棧。
//有沒有等號都對
//序列時刻是遞增的
{
int ph=s.top();
s.pop();//必須先彈棧
//i-s.top()-1表示>=ph的元素的個數
if(!s.empty())
mx=max(mx,(i-s.top()-)*data[ph]);
else
mx=max(mx,i*data[ph]);
}
s.push(i);
}
}
while(!s.empty())
{
int ph=s.top();
s.pop();
if(!s.empty())
mx=max(mx,(n-s.top()-)*data[ph]);
else
mx=max(mx,n*data[ph]);
}
printf("%d\n",mx);
}
return ;
}
拓展問題是求01矩陣的最大子矩陣。
附上鏈接:傳送門。
總結
- 上一篇: netty学习心得1
- 下一篇: 目前流行前端几大UI框架