POJ 3250 單調堆疊

2021-06-08 03:05:46 字數 1637 閱讀 7025

其實今天是第一次聽說這個資料結構。順便ac了一道題目:

所以這個堆疊顯然會滿足一些條件

1. 對於所有當前步驟壓入堆疊的元素e,棧中的其餘元素都是 遞增(或遞減)的大於(或小於)e

2. 對於彈出的所有元素,一定全都 小於或大於e

這個題目第一眼看到應該是乙個 n^2 的暴力搜尋,但是明顯如果用暴力搜尋的話一定會超時。

對於測試資料,我們可以做一下簡單的分析,看看它為什麼可以滿足 單調堆疊 

1037

4122

=

=       =

=   -   =         cows facing right -->

=   =   =

= - = = =

= = = = = =

1 2 3 4 5 6

在這裡,我們用乙個遞減的單調堆疊來描述這個問題,當插入乙個元素e的時候,要求所有的之前的元素都比e要大。

例如當前堆疊t,e1, e2, e3, e4.. en

當前要插入的元素是e

加入eei+1

就是說我們要把ei+1 ... en的元素都彈出來。

為什麼這樣做是合理的呢,觀察可以發現,其實當有e出現在佇列中的時候,ei+1...en這些牛以後就再也看不見任何新的牛了,因為他們被e擋住了。而e1...ei卻都可以看到e的存在,這個時候e的加入會給整個牛隊的【看到頭的數目sum】貢獻. t彈出ei+1...en後的size().

乙份簡單版本的**如下:

#include #include using namespace std;

int main()

sum += t.size();

t.push(ninputnum);

} printf("%lld\n", sum);

} return 0;

}

複雜度分析:如果用暴力搜尋的話,複雜度是o(n^2)

我們現在所用的辦法外面搜尋的時間是n,而對於內部而言,每個元素都至少入棧一次,但是每個元素之多只能出棧一次。所用總的時間複雜度應該是 o(n+n) = o(n)

不過其實這個演算法可以更快一點點,哪怕一點點........

其實我們整個堆疊裡的元素都是從大到小排列的,而我們每次插入乙個元素e的時候,目的都是為了找到那個【第乙個比e小的元素】

有序陣列,找到第乙個比x小的資料下標,這是典型的binary search 問題的變種吧。

這樣快一點點的最後結果是 n+log(n)

所以自己用佇列實現乙個單調堆疊,然後用binary search的方法找插入的合適位置,就能降低一點點複雜度了(從複雜度角度分析來講是沒有提高的)

**如下(第一次嘗試用 文字編輯器寫程式)

#include #define max_cow 80005

long long stack[max_cow];

int nsize;

int findfirstlesselementinarray(long long t)

else

}return nstartidx;

}int main()

printf("%lld\n", sum);

}}

POJ 3250 單調棧模板

題意 從左右給你n頭都面向右牛的高度,每頭牛能被左邊的牛看到當且僅當自己的身高比他低且中間沒有障礙物 求每頭牛能看到的牛數量之和 include include include include include include include include include include inclu...

單調棧應用POJ3250 單調序列

參考 單調棧,顧名思義,是棧內元素保持一定單調性 單調遞增或單調遞減或是其他性質 的棧。我們假如有這樣乙個問題 poj3250 給定一組數,針對每個數,尋找它和它右邊第乙個比它大的數之間有多少個數。如果用樸素的解法就會是雙層for迴圈遍歷,時間複雜度達到o n 2 利用單調棧思想的解法則會降至限行時...

poj3250(單調棧模板題)

題意 求序列中每個點右邊第乙個 自身的點的下標。思路 簡單介紹單調棧,主要用來求向左 右第乙個小於 大於自身的下標,直接求的話複雜度為o n2 而單調棧只有o n 利用好單調棧十分有用。乙個元素向左遍歷的第乙個比它小的數的位置就是將它插入單調棧時棧頂元素的值,若棧為空,則說明不存在這麼乙個數。然後將...