單調棧 矩形牛棚

2022-09-18 04:00:42 字數 2706 閱讀 5699

到底是個資本家,farmer john想通過買更多的奶牛來擴大它的生意。它需要給奶牛建造乙個新的牛棚。 fj買了乙個矩形的r(1 <= r <= 3000)行c(1 <= c <= 3000)列的牧場。不幸的是,他發現某些1 x 1的區域被損壞了,所以它不可能在把整個牧場建造成牛棚了。

fj數了一下,發現有p(1 <= p <= 30000)個1 x 1的損壞區域並且請你幫助他找到不包含損壞區域的面積最大的牛棚。 * (對同乙個損壞區域可能有多次描述——alen.pn注)

輸入

第1行: 三個空格隔開的整數 r, c, and p.

第2..p+1行: 每行包含兩個空格隔開的整數, r和c, 給出乙個損壞區域的行號和列號.

輸出

第1行: 牛棚的最大可能面積

樣例輸入

3 4 2

1 32 1

樣例輸出

6
此題利用單調棧進行求解,題目的意思就是說求乙個破損的矩陣中乙個最大的子矩陣。

用單調棧,單調棧跟單調佇列其實是乙個意思,只不過只有一邊進出。

我們思考一下如果i為子矩陣中高度最小的矩陣,那麼i所能構造的最大子矩陣也就是i左邊第乙個比它矮到i右邊第乙個比它矮的距離再乘上i的高度,那麼原題便轉換成了max(f[i] * h[i])(f[i]表示i左邊第乙個比它矮到i右邊第乙個比它矮的距離,h[i]表示i點的高度。)那麼最關鍵的就是求i的l與r了,這時候單調棧(佇列)就派上用場了。

首先確定思路,我們維護棧內元素呈遞增,那麼裝進h[i]時,便需要在棧裡面彈東西。最後找到適合的放置位置便可以裝入棧退出了。於是在這樣一種操作中就可以求出f[i]了,模擬一下可以知道,當i進棧時,便找到了l,當i出棧時,便找到了r。

於是這道題就可以解決了。

大體思路其實不難。利用這種方法轉換為二維,我們每一排就做一下這樣的一種操作就行了。

這道題錯得很多,雖然錯得也很基礎,但還是一步一步調出來了題。首先就是預處理了。一開始我的預處理是會超時的。

超時預處理**:

scanf ("%d%d%d",&r,&c,&p);

for (int i = 1;i <= r ;i ++ )

for (int j = 1 ; j <= c; j ++ )

sum [i][j] = i;

for (int i = 1;i <= p ;i ++ )

讀者們也一定會發現,有很多算重複了,那麼在p<=30000這麼大的資料範圍,這樣進行預處理太麻煩了。我們便應該想到標記和字首和的思想。如果全部完好,那麼我們就會發現sum[i][j] = sum[i - 1][j] + 1,然後再處理損壞情況。就比如說(i,j)是損壞了的。那麼sum[i + 1][j] = 1。此時如果sum[i][j] == 0, 那麼豈不是就可以按這樣的操作處理?

由於sum陣列本來全都是0,那麼我們先將破損的標記為-1,然後再按平常的操作計算。於是這道題就可以在o(r * c)的時間複雜度下完成,在這一道題是可以過的。當然,這道題亦可不用預處理。但這樣確實要好理解一些。

正確預處理操作(嚇得我還卡個常):

register int i , j , a , b; 

read(r);

read(c);

read(p);

for (i = 1;i <= p ;i ++ )

for (i = 1;i <= r ;i ++ )

sum[i][j] = sum[i-1][j] + 1;}}

自信滿滿地交。wa了。當時心態還算樂觀。馬上回去調**,但一直不過。內心絕望。於是去做和此題差不多,但是用一維的一道題。打著打著,誒,居然寫錯了乙個,把結構體裡面的id寫成了x。當時沒怎麼在意,交上去,對了。。。

那我這題為啥不對,我再次看這個題的**。。。突然發現我居然把這道題的id也寫成x了。。。

wa:ac:

面對這個現實,我感到好笑,同時也找到了自身所存在的問題,下標所對應的值按理說是與下標差距很大的,而我卻沒有看出來這個問題,證明對於程式的除錯還是沒有耐心,不夠仔細。noip**的我的確應該吸取教訓。

最後附上**:

#include#include#include#include#include#include#include#include#include#define maxn 3005

using namespace std;

struct node ;

node(int x,int id)

};stackq;

int r , c , p , sum[maxn][maxn] , bi[maxn] , e[maxn] , ans;

inline void read(int &x)

while (s >= '0' && s <= '9')

x *= f ;

}int main()

for (int i = 1;i <= r ;i ++ )

sum[i][j] = sum[i-1][j] + 1;}}

for (i = 1;i <= r; i ++ )

else

}if (q.empty() && j != c + 1)}}

printf ("%d",ans);

}

最大矩形 單調棧

在這裡先簡單描述一下單調棧 單調棧 一種線性資料結構,棧內元素自棧頂到棧底滿足單調性。有單調遞增棧和單調遞減棧。如果要加入棧的元素不滿足單調性,則要將棧頂元素彈出,直到滿足條件為止,然後將該元素入棧 作用 給乙個直方圖,求直方圖中的最大矩形的面積。例如,下面這個中直方圖的高度從左到右分別是2,1,4...

最大矩形 單調棧

題目 給乙個直方圖,求直方圖中的最大矩形的面積。例如,下面這個中直方圖的高度從左到右分別是2,1,4,5,1,3,3,他們的寬都是1,其中最大的矩形是陰影部分。輸入包含多組資料。每組資料用乙個整數n來表示直方圖中小矩形的個數,你可以假定1 n 100000.然後接下來n個整數h1,hn,滿足 0 h...

貪心 單調棧 最大矩形

貪心 假設當前點為最大矩陣的右下角,向上擴充套件每次取長度的最小值作為矩陣的長。class solution int r matrix.size c matrix 0 size vectorint left r,vector int c,0 for int i 0 i r i int ret 0 f...