演算法詳解 對於單調棧的重新理解

2021-08-30 19:16:12 字數 3206 閱讀 9543

單調棧,就是棧中的元素始終是單調遞增的。

對於某類特殊的問題,若當前狀態與下一狀態的單調性有關,就必須使用單調棧。

題目描述

賢正的某 n 頭奶牛 (1 <= n <= 80,000) 正在過亂頭髮節!由於每頭牛都 意識到自己凌亂不堪的髮型, 寧智賢希望統計出能夠看到其他牛的頭髮的牛的數量。

每一頭牛 i有乙個高度 h[i] (1 <= h[i] <= 1,000,000,000)而且面向東方排成 一排(在我們的圖中是向右)。因此,第i頭牛可以看到她前面的那些牛的頭, (即i+1, i+2,等等),只要那些牛的高度嚴格小於她的高度。

例如這個例子:

牛#1 可以看到她們的髮型 #2, 3, 4 牛#2 不能看到任何牛的髮型 牛#3 可以看到她的髮型 #4 牛#4 不能看到任何牛的髮型 牛#5 可以看到她的髮型 6 牛#6 不能看到任何牛的髮型!

讓 c[i] 表示第i頭牛可以看到髮型的牛的數量;請輸出 c[1] 至 c[n]的和。 如上面的這個例子,正確解是3 + 0 + 1 + 0 + 1 + 0 = 5。

輸入格式

line 1: 牛的數量 n。

lines 2…n+1: 第 i+1 是乙個整數,表示第i頭牛的高度。

輸出格式

line 1: 乙個整數表示c[1] 至 c[n]的和。

樣例資料

input610

37412

2output

5對於這道題目,發現當乙隻新的奶牛進來後,比原來的奶牛要高,那麼這只原來的奶牛無論如何也看不到什麼牛,就屬於無用狀態,顯然只有比新加入的奶牛高才能繼續發揮統計答案的作用。因此,我們可以維護乙個單調遞減的序列:

當新加入的奶牛比棧頂的奶牛矮,答案加上top(表示原來的奶牛都看得到)

當新加入的奶牛比棧頂的奶牛高,把所有比它矮的奶牛從棧中彈出(改狀態無用),答案加top(表示剩下的奶牛都能看得清這乙隻奶牛),並進棧。

演算法原理理解後,就很好實現了。

#include

using

namespace std;

intmain()

cout<

return0;

}

題目描述farmer john的牛們認為,太陽公升起的那一刻是一天中最美好的,在那時她們 可以看到遠方城市模糊的輪廓。顯然,這些輪廓其實是城市裡建築物模糊的影子。   建築物的影子實在太模糊了,牛們只好把它們近似地看成若干個邊長為1單位 長度的正方體整齊地疊在一起。城市中的所有建築物的影子都是標準的矩形。牛們 的視野寬w個單位長度(1<=w<=1,000,000),不妨把它們按從左到右劃分成w列,並 按1~w編號。建築物的輪廓用n組(1<=n<=50,000)數給予描述,每組數包含2個整數 x、y(1<=x<=w,0<=y<=500,000),表示從第x列開始,建築物影子的高度變成了y。 (也就是說,第x[i]列到第x[i+1]-1列中每一列建築物影子的高度都是y[i]個單位 長度)

貝茜想知道這座城市裡最少有多少幢建築物,也就是說,這些影子最少可以由 多少個矩形完全覆蓋。當然,建築物的影子可以有重疊。請你寫乙個程式幫她計算 一下。

題目描述2

對於這道題,我們可以這麼想:

對於擺放的每一塊積木,如果高度要比上乙個矩陣高,那麼必然多出一塊矩陣;

如果高度比上乙個矩陣低,必然上乙個矩陣要多出來;如果高度相等,則當前高度可以補到前面的高度上面去。

因此,維護乙個單調遞增的棧:

1.比棧頂高,進棧。

2.比棧頂低,彈出比它高的矩陣,累加答案;繼續進棧。

3.和棧頂一樣高,什麼都不做。

#include

using

namespace std;

int n,w,k,ans=

0,a[

600000]=

,top=

0,st[

600000]=

;int

main()

for(

int i=

1;i<=n;i++

)//如果小,則把比它大的元素彈出

對於每乙個矩陣,如果下乙個比它高,凸出的部分必然沒有;因此我們只需要使用單調棧維護單調遞增,再用另外乙個陣列維護這個方塊的高度往左最多能夠放下的寬度即可。

#include

using

namespace std;

#define maxn 100100

#define qword long long

int n;

int s[maxn]

;int a[maxn]

;int w[maxn]

;inline

void

read

(int

&readnum)

while

(c>=

'0'&& c<=

'9') s=s*

10+c-

48,c=

getchar()

; readnum=s*w;

}inline

void

mem(

void

)void

work

(void

) s[

++t]

=a[i]

,w[t]

=sum+1;

//進棧,標記當前高度最大能往左放幾個格仔 }}

printf

("%lld\n"

,ans);}

intmain

(void

)return0;

}

演算法 單調棧

單調棧 從左往右進行遍歷,如果棧頂元素大於等於當前的元素,直接出棧 while 迴圈 退出while 迴圈兩個條件,棧空,或者棧不為空,此時棧頂元素小於單前元素 if 如果棧不為空,表明棧頂元素小於當前元素,將棧頂元素儲存在當前元素對應下標的陣列中 從右邊向左進行遍歷 while 如果棧頂元素大於當...

簡單的單調棧演算法

目錄應用 單調棧是一種演算法,它可以用一次掃瞄 o n 時間求出序列中每個數向左和向右的第乙個大於它的數,也可以用一次掃瞄 o n 時間求出序列中每個數向左和向右的第乙個小於它的數。以大於為例 用單調棧求左邊第乙個大於的數 有數列 big 對於乙個數 a i 前面的兩個數 a p,a q,quad ...

單調棧演算法筆記

定義 單調棧就是棧內元素遞增或者單調遞減的棧,並且只能在棧頂操作。單調棧的維護是o n 的時間複雜度,所有元素只會進進棧一次 性質 單調棧裡面的元素具有單調性 元素加入棧前會把棧頂破壞單調性的元素刪除 使用單調棧可以找到元素向左遍歷的第乙個比他小的元素 單增棧 也可以找到元素向左遍歷第乙個比他大的元...