單調佇列 廣告印刷

2021-06-19 00:12:14 字數 3951 閱讀 5697

【問題描述】

最近,afy決定給toj印刷廣告,廣告牌是刷在城市的建築物上的,城市裡有緊靠著的n個建築。

afy決定在上面找一塊盡可能大的矩形放置廣告牌。我們假設每個建築物都有乙個高度,

從左到右給出每個建築物的高度h1,h2…hn,且0

要求輸出廣告牌的最大面積。

【輸入檔案】

輸入檔案 ad.in 中的第一行是乙個數n (n<= 400,000)

第二行是n個數,分別表示每個建築物高度h1,h2…hn,且0輸出檔案 ad.out 中一共有一行,表示廣告牌的最大面積。

【輸入樣例】

65 8 4 4 8 4

【輸出樣例】24

思路:容易想到,要想使面積最大,肯定要將當前廣告覆蓋的樓房中,高度最小的那個樓房全部印刷上廣告。所以,

列舉每個建築物的高度作為廣告矩形的高度,求出在該樓房的左側,有多少棟連續的樓房的高度大於或等於該樓房的高度,右側同理。然後得到矩形廣告的面積,找出最大面積即可。

列舉法,時間複雜度為o(n^2):

int maxrectarea(void)

//右邊同理

for (j = i+1; j < n && h[j] >= h[i]; j++)

int area = count * h[i];

if (area > maxarea)

}return maxarea;

}

使用單調佇列優化,時間複雜度為o(n):

在這裡約定,以當前建築物為矩形高度,向兩側尋找可以印刷的建築的過程叫做——擴充套件。

我們來考察從第i個建築向左擴充套件的情況,h陣列為建築物高度,下標為1~n:

如果我們知道,向左擴充套件到極限時的建築物的下標為j的話,這時,建築物j是第乙個滿足h[j]

如果,對h從左向右建立乙個單調遞增佇列mq,h陣列的下標為佇列元素,在新的建築物i要入隊時,將隊尾所有高度大於等於h[i]的元素都出隊,新的隊尾mq[rear-1](rear指向隊尾的下乙個位置)剛好是上面所講的向左擴充套件的極限下標j,因為入隊順序是從左向右的,而且在極限下標j與當前建築下標i之間的這些建築,因為高度大於等於h[i],所有都出隊了,mq[rear-1]就剛好是極限下標j。

向右側擴充套件是同樣的道理,只需要對h從右向左建立乙個單調遞增佇列即可。

為了簡化操作,將h[0]和h[n+1]的值都賦為-1。

下面舉乙個向左側擴充套件的例子:

h儲存建築物高度,l記錄向左擴充套件建築數量,藍色代表該建築已經計算過,紅色代表剛剛計算過的建築物。

下標    

0    

1    

2    

3    

4    

h     -1

9    

5    

5    

-1    

l    

單調遞增佇列,front和rear分別為隊首和隊尾指標,rear指向隊尾的下乙個位置,初始時讓0號建築入隊

指標    

front    

rear    

佇列元素    

0    

1號建築入隊,隊尾沒有比1號建築更高的建築,直接入隊,l[1]= 1 - mq[rear-1] - 1,結果如下:

下標    

0    

1    

2    

3    

4    

h    

-1    

9    

5    

5    

-1    

l    

0    

指標    

front    

rear    

佇列元素    

0    

1     

2號建築入隊,隊尾元素為1號建築,高度為9,比2號建築高,所以出隊,新的隊尾元素為0號,計算l[2] = 2 –mq[rear-1] – 1,然後2號建築入隊尾,結果如下

下標    

0    

1    

2    

3    

4    

h    

-1    

9    

5    

5    

-1    

l    

0    

1    

指標    

front    

rear    

佇列元素    

0    

2     

3號建築入隊,隊尾元素為2號建築,高度為5,與3號建築一樣高,所以出隊,新的隊尾元素為0號,計算l[3] = 3 –mq[rear-1] – 1,然後3號建築入隊尾,結果如下:

下標    

0    

1    

2    

3    

4    

h    

-1    

9    

5    

5    

-1    

l    

0    

1    

2    

指標    

front    

rear    

佇列元素    

0    

3     

最終結果:

下標    

0    

1    

2    

3    

4    

h    

-1    

9    

5    

5    

-1    

l    

0    

1    

2    

**:

#include #define maxn 1000000

int h[maxn+5]; //建築物的高度

int n; //建築物的數目

int mq[maxn+5]; //單調佇列,對內元素為建築物高度的下標

int left[maxn+5]; //left[i]:在第i個建築物左側,不比它的高度小的建築物數量

int right[maxn+5]; //right[i]:在第i個建築物右側,不比它的高度小的建築物數量

void calcleft(void)

left[i] = i - mq[rear-1] - 1;

mq[rear++] = i; }}

void calcright(void)

right[i] = mq[rear-1] - i - 1;

mq[rear++] = i; }}

int maxrectarea(void)

} return maxarea;

}int main(void)

h[0] = h[n+1] = -1;

calcleft();

calcright();

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

cout << endl;

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

cout << endl;

cout << maxrectarea() << endl;

} return 0;}/*

65 8 4 4 8 4

69 5 8 2 8 8

69 6 8 2 8 8

*/

單調佇列 廣告印刷

至今沒有找到出處的題目,但是手裡碰巧有一套測試資料,缺測試資料的人可以問我要。經典單調佇列,這位的博文說的很清楚,我就不多闡述了。1 include2 include3 include4 include5 6using namespace std 7const int maxn 400000 8 i...

單調佇列水題 刷廣告

問題描述 最近,afy決定給toj印刷廣告,廣告牌是刷在城市的建築物上的,城市裡有緊靠著的n個建築。afy決定在上面找一塊盡可能大的矩形放置廣告牌。我們假設每個建築物都有乙個高度,從左到右給出每個建築物的高度h1,h2 hn,且0 要求輸出廣告牌的最大面積。輸入檔案 輸入檔案 ad.in 中的第一行...

SOJ 393 廣告印刷

題目描述 最近,afy 決定給 toj 印刷廣告,廣告牌是刷在城市的建築物上的,城市裡有緊靠著的 n nn 個建築。afy 決定在上面找一塊盡可能大的矩形放置廣告牌。我們假設每個建築物都有乙個高度,從左到右給出每個建築物的高度 h 1h 1 h1 h 2h 2 h2 h nh n hn 且 0 00...