單調佇列入門

2022-05-29 20:27:18 字數 1924 閱讀 8343

單調佇列這個名字就指明了它的性質——單調性,是乙個單調的雙端佇列

下面列出deque的常用成員函式:來自:

單調佇列入門題目:p1886 滑動視窗 /【模板】單調佇列

這裡我們只討論最大值,最小值原理一樣的

很明顯,當我們在計算區間[i−k+1,i]的最大值時,是不是區間[i−k+1,i−1]我們之前已經計算過了?那麼我們是不是要儲存上一次的結果呢(主要是最大值)?

這時,單調佇列登場——單調佇列主要有兩個操作:刪頭和去尾

1.刪頭

如果佇列頭的元素離開了我們當前操作的區間,那麼這個元素就沒有任何用了,我們就要把它刪掉

2.去尾

假設即將進入佇列的元素為x,佇列尾指標為tail,這時我們要比較二者的大小:

1* x2* x>=q[tail] 此時,佇列遞減性被打破,此時我們做一下操作:

① 彈出隊尾元素:因為當前的q[tail]不但不是最大值,對於以後的情況也不如x,所以要彈出

②重複執行①,直到滿足x③將xx入佇列

對於樣例而言:

[1 3 -1] -3 5 3 6 7

q=,, output:3

1 [3 -1 -3] 5 3 6 7

q= output:3

1 3 [-1 -3 5] 3 6 7

q=,, output:5

1 3 -1 [-3 5 3] 6 7

q= output:5

1 3 -1 -3 [5 3 6] 7

q=, output:6

1 3 -1 -3 5 [3 6 7]

q= output:7

由於每個元素最多入隊一次,出隊一次,所以時間複雜度為o(n)

當然,這題還可以用st表和線段樹來做,但都沒有單調佇列方便

實現:由於要對隊首和隊尾進行維護,所以我們需要使用雙端佇列

ac_code

1 #include 2

using

namespace

std;

3 typedef long

long

ll;4

const

int maxn = 1e6+10;5

const ll inf=0x3f3f3f3f3f3f3f3f;6

#define dep(i,first,last) for(int i=first;i>=last;i--)

7#define rep(i,first,last) for(int i=first;i<=last;i++)

8#define lson l,mid,pt<<1

9#define rson mid+1,r,pt<<1|1

1011 templatevoid read(t &a)

18while

( isdigit(ch) )

22 a=f?x:-x;23}

2425 dequeq;

26int

a[maxn],n,m;

27int

main()

2839

}40 printf("\n"

);41

while(!q.empty()) q.pop_front();

42 rep(i,1

,n)49

}50 printf("\n"

);51

return0;

52 }

單調佇列 入門

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

單調佇列入門

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

單調佇列入門

給定長度為n的數列a和整數k,求b i min,複雜度為o n 最開始單調隊列為空,保證佇列中的元素始終保持單調性 為了計算b 0 把0到k 1依次加入佇列。在加入i時,當單調佇列的末尾的值j滿足a j a i 則不斷取出。直到雙端隊列為空或者a j a i 之後再於末尾加入i。等到k 1加入佇列,...