1. 程式人生 > >單調佇列 和 單調棧

單調佇列 和 單調棧

單調佇列

定義

有一個佇列(雙端佇列), 佇列中的元素滿足下面四種狀態的任何一種都為單調佇列:

  • 單調遞增 (如 1 2 3 5 9)
  • 單調不減 (如 1 2 3 3 5)
  • 單調遞減 (如 9 5 3 2 1)
  • 單調不增 (如 5 3 3 2 1)

性質

 (以單增佇列為例)
 插入時,需要將尾部大於此數的全部出隊。
 刪除時,根據需要使隊首或者隊尾的元素出隊(所以要用雙端佇列)。
 每時每刻隊首元素都代表著當前區間範圍內的最小值。
 單調佇列維護元素值的同時也要維護元素的下標,以便知道每個元素和整個區間的關係。

實現

int
q[maxn], p[maxn], ft, rr; for(int i = 1; i <= n; ++i) { while(rr > ft && q[rr-1] >= a[i]) --rr; q[rr++] = a[i], p[rr-1] = i; //if(p[ft]<k) ++ft; }

應用

 個人對單調佇列有以下幾點感覺:
 單調佇列多用於區間問題,而且大多數是區間長度或者其他的有限制的問題。
 單調佇列的研究物件一般是某個元素,而非某個區間(個人感覺), 個人感覺要維護的基本上是某個元素的一些相關屬性。
 有幾個題目作為例子:

 另外單調佇列還有一個大用處就是優化一種形式的dp, 由於我還沒有研究到dp,這裡就先放一放,列一下知識點和一個題目感受一下。

(以下言論來自百度百科, 不可全信)
做動態規劃時常常會見到形如這樣的轉移方程:

f[x] = max or min { g(k) | b[x] <= k < x } + w[x]

其中b[x]隨x單調不降,即b[1]<=b[2]<=b[3]<=…<=b[n]
(g[k]表示一個和k或f[k]有關的函式,w[x]表示一個和x有關的函式)

 這個方程怎樣求解呢?我們注意到這樣一個性質:如果存在兩個數j, k,使得j <= k,而且g(k) <= g(j),則決策j是毫無用處的。因為根據b[x]單調的特性,如果j可以作為合法決策,那麼k一定可以作為合法決策,並且k是一個比j要優的決策。因為k比j要優,(注意:在這個經典模型中,“優”是絕對的,是與當前正在計算的狀態無關的),所以,如果把待決策表中的決策按照k排序的話,則g(k)必然是不降的。在此例中決策表即f[x].
這樣,就引導我們使用一個單調佇列來維護決策表。對於每一個狀態f(x)來說,計算過程分為以下幾步:

1、 隊首元素出隊,直到隊首元素在給定的範圍中。
2、 此時,隊首元素就是狀態f(x)的最優決策,
3、 計算g(x),並將其插入到單調佇列的尾部,同時維持佇列的單調性(不斷地出隊,直到佇列單調為止)。

 重複上述步驟直到所有的函式值均被計算出來。不難看出這樣的演算法均攤時間複雜度是O(1)的。因此求解f(x)的時間複雜度從O(n^2)降到了O(n)。
 單調佇列指一個佇列中的所有的數符合單調性(單調增或單調減),在資訊學競賽的一些題目上應用,會減少時間複雜度.
 可以參考下面這道題理解

單調棧

定義

 個人感覺這個棧和佇列是差不多的,其實單調棧只要在單調佇列的基礎上,關掉佇列的一個端點不就行了, 只能在一端操作就是棧了,所以在實際的編碼中單調棧和單調佇列是差不多的(還是個人感覺)。

性質

 同單調佇列

實現

 同單調佇列

應用

目前我做到的四道題都只是用來求一個問題的:
就是在一個數組中, 求一個元素和它向左向右不比它小的元素所能組成的最大的區間,就是它最遠能擴充套件到的地方,這應該是單調棧最簡單的應用了(還沒做到難的)。

另外還有三道題和這題差不多,我這裡給出題目連結, 讀者可作為練習實驗下。

相關推薦

單調佇列單調

目錄 單調棧 什麼是單調棧 單調棧的應用 排隊遞減單調棧 最大長方形遞增單調棧 單調佇列 什麼是單調佇列 單調佇列的應用 單調佇列的基本模板 單調佇列的重要應用DP 單調棧 什麼是單調棧 什麼叫做單調棧? 什麼是單調? 單調也就是序

矩形牛棚——淺談C++單調佇列單調

矩形牛棚    BZOJ    1114 目錄 前言 正文 解析 單調棧 前言 厲害的是,這道題在LGOJ上面又沒有。 這道題也算花了我比較多的時間哈,不過其實只是利用單調棧求解一個最大長方形。 正文 題目描述

單調佇列 單調

單調佇列 定義 有一個佇列(雙端佇列), 佇列中的元素滿足下面四種狀態的任何一種都為單調佇列: 單調遞增 (如 1 2 3 5 9) 單調不減 (如 1 2 3 3 5

Leetcode 221. Maximal Square 單調佇列dp兩種思路求解

題意 給定一個0,1矩陣,希望找到矩陣中的一個面積最大的聯通正方形區域,這個區域中全是1 思路 基本思路:找面積最大的,其實就是找最長的邊長,我們的思路都是以這個為出發點的 dp思路 整體來看,就是一個二維dp,是這類矩陣問題的一個

[模板]單調佇列單調

目錄 單調佇列:滑動視窗(算是重要的板題了) 單調棧:最大矩形面積 總結 首先給一道板題:滑動視窗(十分重要,基本後面的複雜題由此題思路進行優化) 題目描述 給你一個長度為N的陣列,一個長為K的滑動的窗體從最左移至最右端,你只能見到視窗的K個數,每次窗體向右移動一位,如下

單調佇列單調用法詳解

基本資料結構的應用一 棧和佇列 單調棧 單調佇列 和  優先佇列的應用 1.單調棧 單調棧是指一個棧內部的元素是具有嚴格單調性的一種資料結構,分為單調遞增棧和單調遞減棧。 單調棧有兩個性質 1.滿足從

單調佇列單調總結

最近幾天接觸了單調佇列,還接觸了單調棧,就總結一下。 其實單調佇列,和單調棧都是差不多的資料型別,顧名思義就是在棧和佇列上加上單調,單調遞增或者單調遞減。當要入棧或者入隊的時候,要和棧頭或者隊尾進行比較,滿足單調的性質則入隊入棧,否則將當前元素刪去,直到滿足單

C++11執行緒安全佇列安全

文章程式碼取自C++11併發程式設計指南,記錄於此方便日後檢視 #include "stdafx.h" #include <thread> #include <iostream> #include <vector> #include &l

單調單調佇列的入門

轉載地址:https://www.cnblogs.com/tham/p/8038828.html 我自己的話單調棧是也用陣列模擬出來的,我是根據這個部落格學的,原理挺簡單的,但是做題思想的轉變有點麻煩,最後陣列模擬的單調佇列其實是雙向佇列。 下邊是大佬的部落格: 單調佇列是什麼呢?可以直

suoi65 區間最小值的 (單調+莫隊+rmq)

傳送門 這題好妙妙啊 首先,如果我知道[l,r],要轉移到[l,r+1]的時候,就是加上以r+1為右端點,[l,r+1]為左端點的區間的最小值,其他情況和這個類似 考慮這玩意怎麼求 右端點固定的話,我左端點越往左走,這個最小值一定是越來越小 找到[l,r+1]範圍內的最小值mi,那麼在mi前面的第一

【演算法競賽進階指南】單調佇列CH1201最大子序列

輸入一個長度為n的整數序列,從中找出一段不超過m的連續子序列,使得整個序列的和最大。下標位置遞增、對應的字首和S的值也遞增的序列為最優的選擇策略我們掃描i,對i進行如下操作1.判斷隊頭與i的距離與m的關係來決策是否出隊2.更新答案3.刪除隊尾決策使整個佇列單調 n=6 m=4輸入資料:1 -3 5 1 -2

筆記——單調佇列&&單調優化DP

眾所周知 動態規劃 的 題 往往 推了a long time 但是o(n^3) 於是就自閉了 所以我們有了 單調佇列和棧 這種東西 神奇的單調佇列 有這麼一道題 樸素 o(n^2) 亂搞 o(nlog n)(線段樹、RMQ) 然後。。。 單調佇列 o(

1215 】陣列的寬度 (單調 或 分治 或 單調佇列,算貢獻,需去重)

題幹: N個整陣列成的陣列,定義子陣列aii..ajj的寬度為:max(ai..aj) - min(ai..aj),求所有子陣列的寬度和。 Input 第1行:1個數N,表示陣列的長度。(1 <= N <= 50000)  第2 - N + 1行:每行1個數

牛可樂發紅包脫單ACM賽$ C-區區區間間間(單調or單調佇列

思路來源 題解 看標程那個看不懂,只好看這個 反正就是求一個區間最值的貢獻,以後見到用這個板子就好了... 很固定很套路很裸的區間最值... 標程給了我們這個提示,化簡式把負號放進後項裡去,相當於 求數列an最大值的區間貢獻+數列bn最大值的區間貢

佇列_單調佇列_CH1201_最大子序

思路分析:     這是一道典型的單調佇列應用問題, 先給出AC程式碼, 然後給出程式正確性證明和時間複雜度分析. //CH1201_最大子序和 #include <cstdio>

揹包模板(01,完全,多重揹包的二進位制優化單調佇列優化

揹包問題 1,01揹包 揹包問題的基礎,總體積為V的揹包,有n件體積v【i】,價值w【i】的物品,求能裝物品的最大總價值 void zero(int v,int w) { for(int j=V;j>=v;j--) { dp[j]=max(dp[j],dp[j

poj 2823 單調佇列入門題(內含手寫佇列的學習模板)

Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 39011 Accepted: 11554 Case Time Limit: 5000MS Descripti

C++動態規劃及單調佇列的優化————擁擠的奶牛(擠奶牛Crowded Cows)彈簧高蹺(POGO的牛Pogo-Cow)

題目描述: FJ的n頭奶牛(1<=n<=50000)在被放養在一維的牧場。第i頭奶牛站在位置x(i),並且x(i)處有一個高度值h(i)(1<=x(i),h(i)<=1000000000)。 一頭奶牛感覺到擁擠當且僅當它的左右兩端都有一頭奶牛所在的高度至少是它的2倍,

單調單調佇列詳解』

單調棧 性質 單調棧是一種特殊的棧,特殊之處在於棧內的元素都保持一個單調性,可能為單調遞增,也可能為單調遞減。 模型 例如下圖就是一個單調遞增的單調棧。 其中的元素從小到大排列。 那麼,如果我們要加入一個新的元素5,5>4,符合要求,就可以直接加入。

hdu3415 單調佇列求區間最大

Problem Description Given a circle sequence A[1],A[2],A[3]......A[n]. Circle sequence means the left neighbour of A[1] is A[n] , and