單調佇列這個名字就指明了它的性質——單調性,是乙個單調的雙端佇列
下面列出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 2using
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加入佇列,...