單調佇列與普通佇列不一樣的地方就在於單調佇列既可以從隊首出隊,也可以從隊尾出隊。
那麼我們應該怎樣實現單調佇列呢?
就拿樣例來談談,設以最小的為標準。
8 3
1 3 -1 -3 5 3 6 7
下文中我們用q來表示單調佇列,p來表示其所對應的在原列表裡的序號。1.由於此時隊中沒有乙個元素,我們直接令1進隊。此時,q=,p=。
2.現在3面臨著抉擇。下面基於這樣乙個思想:假如把3放進去,如果後面2個數都比它大,那麼3在其有生之年就有可能成為最小的。此時,q=,p=
3.下面出現了-1。隊尾元素3比-1大,那麼意味著只要-1進隊,那麼3在其有生之年必定成為不了最小值,原因很明顯:因為當下面3被框起來,那麼-1也一定被框起來,所以3永遠不能當最小值。所以,3從隊尾出隊。同理,1從隊尾出隊。最後-1進隊,此時q=,p=
4.出現-3,同上面分析,-1>-3,-1從隊尾出隊,-3從隊尾進隊。q=,p=。
5.出現5,因為5>-3,同第二條分析,5在有生之年還是有希望的,所以5進隊。此時,q=,p=
6.出現3。3先與隊尾的5比較,3<5,按照第3條的分析,5從隊尾出隊。3再與-3比較,同第二條分析,3進隊。此時,q=,p=
7.出現6。6與3比較,因為3<6,所以3不必出隊。由於3以前元素都<3,所以不必再比較,6進隊。因為-3此時已經在滑動視窗之外,所以-3從隊首出隊。此時,q=,p=
8.出現7。隊尾元素6小於7,7進隊。此時,q=,p=。
那麼,我們對單調佇列的基本操作已經分析完畢。因為單調佇列中元素大小單調遞*(增/減/自定義比較),因此,隊首元素必定是最值。按題意輸出即可。
原題解**可見上面鏈結,下面我寫一點原題解基礎上的個人理解:(還不太理解單調佇列的建議先看上面的題解~)
將佇列中肯定不滿足條件的所有
元素提前從隊尾出隊。
將當前要處理的元素從隊尾入隊。
將佇列中已經過期的所有
元素從隊首出隊。
tips:注意步驟一中的所有一詞,解釋了不用if
而用while
int p[
1010000];
//原陣列
int q[
1010000];
//單調佇列:記錄佇列中的值
int q_pos[
1010000];
//記錄佇列中的值的下標
intmain()
cout << endl;
return0;
}
單調佇列 滑動視窗
nkoj 2152 description 給你乙個長度為n n 10 6 的陣列,乙個長為k的滑動的窗體從最左移至最右端,你只能見到視窗的k個數,每次窗體向右移動一位,找出窗體所包含的數字的最大和最小值,如下表所示 k的值為3 視窗位置 最小值 最大值 1 3 1 3 5 3 6 7 1 3 1 ...
滑動視窗 單調佇列
給定乙個大小為n 106的陣列。有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。您只能在視窗中看到k個數字。每次滑動視窗向右移動乙個位置。以下是乙個例子 該陣列為 1 3 1 3 5 3 6 7 k為3。視窗位置 最小值 最大值 1 3 1 3 5 3 6 7 1 3 1 3 1 3 5 3...
單調佇列 滑動視窗
p1886 滑動視窗 模板 單調佇列 有乙個長為 n 的序列 a,以及乙個大小為 k 的視窗。現在這個從左邊開始向右滑動,每次滑動乙個單位,求出每次滑動後視窗中的最大值和最小值。如果按照暴力方法做的話,每一次判斷相鄰的k個數的最大值和最小值,複雜度為o n k 肯定會超時,因此就想到把每次的最大值和...