剛學單調佇列時,在網上各大部落格找文章學,說實話,寫得很雜,表示自己懵逼了些許,最後硬是啃出來了,所以我決定要寫一篇能讓大部分人都看懂的部落格來。
說單調佇列,那我們就先說說這個單調佇列是個什麼物種。單調佇列從字面上看,無非就是
有某種單調性
的佇列,沒錯,這就是所謂的單調佇列。
單調佇列
它分兩種,
一種是單調遞增的,另外一種是單調遞減的。
不斷地向快取陣列裡讀入元素,也不時地去掉最老的元素,不定期的詢問當前快取陣列裡的最小的元素。
用單調佇列來解決問題,一般都是
需要得到當前的某個範圍內的最小值或最大值。
舉個例子:有 7 6 8 12 9 10 3 七個數字,現在讓你找出範圍( i-4,i ) 的最小值。
那我們就可以這樣模擬一遍。
先初始化 (表示i=0時的值)
i=1 ->
(表示i=1,時,在其範圍內最小的值為0)
-> 7進隊
;
i=2->
(表示i=2,時,在其範圍內最小的值為7)
->
6比7小,7出,6進
;
i=3->
(表示i=3,時,在其範圍內最小的值為6)
->8比6大,8進
;
i=4->
(表示i=4,時,在其範圍內最小的值為6)
->
12比8大,12進
;
i=5->
(表示i=4,時,在其範圍內最小的值為6)
-> 9比12小,12out,9比8大,9進
;
i=6->
但是 單調佇列中元素6的下標是2,不在(2, 6],中,
故6 out,這就是單調佇列的精髓了。故單調隊列為
(表示i=5,時,在其範圍內最小的值為8)
->10比9大,10進 最終 單調隊列為
;
i=7->
(表示i=6,時,在其範圍內最小的值為8)
->
3比單調隊列為 的任意值都小,故全out,最終集合為
;
相信大家看完這個例子了解得有些吧,再次重申一遍,單調佇列的
核心(我認為的哈):
得到當前的某個範圍內的最小值或最大值。
要不是這樣的話,那還有必要這麼麻煩找嗎,直接找前面最小的就好了,可事實不是這樣,題目是有限制的,規定在某個範圍內找。
那我們就來看到例題,加深理解:
description
乙個長度為n的整數序列,從中找出一段不超過m的連續子串行,使得整個序列的和最大。
例如: 1, -3, 5, 1, -2, 3
當m=4時,sum = 5+1-2+3 = 7
當m=2或m=3時,sum = 5+1 = 6
input
多測試用例,每個測試用例:
第一行是兩個正數n, m ( n, m ≤ 300000 )
第二行是n個整數
output
每個測試用例輸出一行:乙個正整數,表示這n個數的最大子序和長度
sample input
6 41 -3 5 1 -2 3
sample output 7
這題可以用dp來解,在這我們就用單調佇列來解。
我們先把序列的
前i項和加起來
並存到乙個陣列sum[ ]上,那麼
任意連續的子串行和
就為sum [ i ] - sum[ j ]
(i>j && j>i-m
)。
那麼我們就可以跟上述例子一樣,一直更新就好了,每次
找出在(i-m,i)範圍內的
最小sum[j]值。
**一:
#include#include///單調佇列,
#include#includeusing namespace std;
typedef long long ll;
const int maxn=300010;
ll sum[maxn];
list que;
int main()
///初始化
ll maxs=sum[1];
que.push_front(1);
for(int i=2;i<=n;i++)
///初始化
int left=1,right=1;
index1[1]=1;
ll tmax=sum[1];
for(int i=2;i<=n;i++)
{while(index1[left]=left&&sum[i]
我的標籤:做個有情懷的程式設計師!
單調佇列詳解
剛學單調佇列時,在網上各大部落格找文章學,說實話,寫得很雜,表示自己懵逼了些許,最後硬是啃出來了,所以我決定要寫一篇能讓大部分人都看懂的部落格來。說單調佇列,那我們就先說說這個單調佇列是個什麼物種。單調佇列從字面上看,無非就是有某種單調性的佇列,沒錯,這就是所謂的單調佇列。單調佇列它分兩種,一種是單...
單調棧 單調佇列詳解
首先看乙個問題。給定乙個數列,從左至右輸出每個長度為 k 的數列段內的最小數和最大數 第一行輸出每個區間最小值,第二行輸出最大值 數列長度 n leq 10 6 k leq n 解法 很直觀的一種解法,那就是從數列的開頭,找到這最開始的k個數的最大值,然後後移乙個單元,繼續找到k個數中的最大值。這種...
dp單調佇列(詳解)
我們從最簡單的問題開始 給定乙個長度為n的整數數列a i i 0,1,n 1和窗長度k.要求 f i max,i 0,1,n 1 問題的另一種描述就是用乙個長度為k的窗在整數數列上移動,求窗裡面所包含的數的最大值。解法一 很直觀的一種解法,那就是從數列的開頭,將窗放上去,然後找到這最開始的k個數的最...