單調棧以及單調佇列入門

2021-09-26 16:05:11 字數 2456 閱讀 2330

一、單調棧

單調棧是指乙個棧內部的元素具有嚴格單調性的一種資料結構,分為單調遞增棧和單調遞減棧。

其具有以下兩個性質:

1,滿足棧底到棧頂的元素具有嚴格單調性。

2,滿足棧的先進後出特性,越靠近棧頂的元素越後出棧。

元素進棧過程:

對於乙個單調遞增棧來說,若當前進棧的元素為a,如果a《棧頂元素,則直接將a進棧。

如果a≥棧頂元素,則不斷將棧頂元素出棧,直到滿足a《棧頂元素。

假設維護乙個單調上公升的棧。如果入棧元素小於棧頂那麼就要開始pop。而pop掉的元素一定全都大於這個入棧元素。單調棧內的兩個相鄰元素a,b如果在原序列中不是相鄰的,則意味著b的出現pop掉了中間的元素,因此這中間的元素必定都大於b。

乙個元素的進入彈掉了一部分元素,由此求出最左延伸量。如果乙個元素即將被pop,意味著終於出現了乙個比它小的,就可以求出最右延伸量了。

時間複雜度分析

對於每個元素,其有且僅有一次插入,最多出現一次刪除,故其時間複雜度為o(n)。

例題:hdu1506**如下:

#include

#define ll long long

#define maxn 100010

using namespace std;

int h[maxn]

,l[maxn]

,r[maxn]

;stack<

int> s;

intmain()

while

(!s.

empty()

)for

(int i=

1;i<=n;i++)if

(s.empty()

)else

s.push

(i);

}while

(!s.

empty()

)for

(int i=n;i>=

1;i--)if

(s.empty()

)else

s.push

(i);

}for

(int i=

1;i<=n;i++

) cout<

}return0;

}

二、單調佇列單調佇列與單調棧及其相似,把單調棧先進後出的性質改為先進先出既可。

元素進佇列的過程對於單調遞增佇列。

對於乙個元素a,如果a>隊尾元素,那麼直接將a扔進佇列,如果a≥隊尾元素,則將隊尾元素出佇列,直到滿足 a>隊尾元素即可。

注意:一般的佇列不支援隊尾刪除,所以一般用雙端佇列dequeue,但是用陣列模擬就不存在這樣的問題

時間複雜度分析

對於每個元素,其有且僅有一次插入,最多出現一次刪除,故其時間複雜度為o(n)。

例題:hdu 3530**如下:

#include

#define ll long long

#define maxn 200010

using namespace std;

int a[maxn]

;deque<

int> q1,q2;

intmain()

while

(!q1.

empty()

)while

(!q2.

empty()

)int flag=0;

for(

int i=

1;i<=n;i++

) q1.

push_front

(i);

while

(!q2.

empty()

&&a[i]

front()

])q2.

push_front

(i);

while

(!q1.

empty()

&&!q2.

empty()

&&a[q1.

back()

]-a[q2.

back()

]>k)

else}if

(!q1.

empty()

&&!q2.

empty()

&&a[q1.

back()

]-a[q2.

back()

]>=m)

} cout<

}return0;

}

——————後序補充中。。。。。

單調棧與單調佇列入門

特點1 top指向最後乙個數所在位置 特點2 後進先出 特點3 遞增或遞減 例題 poj2796 大意 求乙個區間,這個區間內 所有數的和sum 區間內min 的值 相比其他區間大 輸入 6 3 1 6 4 5 2 輸出 60 3 5問題 求出每個數在哪個區間內最小 區間怎麼求 將這個數 區間總值 ...

單調佇列 入門

今天寫了人生中第乙個單調佇列,激動ing 先看一道單調佇列的入門題 乙個含有n項的數列 n 2000000 求出每一項前面的第m個數到它這個區間內的最小值。先寫出動規方程 f i min j合法 很明顯的,這是乙個n 2的動規,但是,我們可以注意到,數列中有些數無論如何都不會被選到.如 1 2 8 ...

單調佇列入門

單調佇列是一種佇列 廢話 其中佇列的元素保證是單調遞增或者是單調遞減的 那麼隊首的元素不就是最小 或最大 的嗎?我們結合具體的題目來看看吧 傳送門 p1886 滑動視窗 現在有一堆數字共n個數字 n 10 6 以及乙個大小為k 的視窗。現在這個從左邊開始向右滑動,每次滑動乙個單 位,求出每次滑動後視...