沒用的話:好像好久沒更博了,無聊就講講演算法吧(主要找不到水題)。
認識rmq:
要學習rmq,首先要知道rmq問題是什麼吧?
rmq簡單來說就是求區間的最大值(最小值)。
什麼?沒懂!
舉個栗子:
1 -2 9 10 15 38 -9
這裡有 7 個數(隨便輸的),rmq就是用來查詢這些數中的最大值(最小值),但是是區間的。比如查詢 [1,3] 這個區間的最大值 就是 9 這個值 .
這樣講應該懂了吧。
暴力解法:
其實這樣的題目可以直接暴力對吧,一重迴圈列舉區間就好了。
但是如果有多個詢問效率顯然就低了很多,因為可能會重複計算。
所以會有人想到dp吧。
rmq解法:
而rmq的一解法就是乙個神奇dp。(當然你也可以線段樹)
rmq感覺很少用到,但這個dp思想卻能有很大啟發! (具體來講,這個思想是倍增)
進入正題——rmq(以下以求最大值為例)
f[i,j]表示 從 i 開始 到i+2j -1(可能不是很清楚,是二的 j 次方再減一)這個區間中的最大值
什麼?為什麼要用 2j 這麼奇怪的東西? 這就是rmq的神奇
然後就是初始值了 顯然 f[i,0]=a[i](原始陣列) 對吧 因為 20 等於1 乙個數的區間最大值肯定就是這個數 你總不會說 [2,2] 這個區間的最大值在[3,3]這個區間吧?
辣麼狀態轉移方程呢?
f[i,j]=max(f[i,j-1],f[i+2j-1,j-1])
這麼啪給你肯定是不懂的
自己畫了張圖:
假如要求綠色這段區間的最大值,實際上主要這段藍色這段區間的最大值和紅色這段區間的最大值就可以了對吧,
綠色這段區間的最大值就會等於max(藍色最大值,紅色最大值)
因為dp是遞推而來的,所以藍色最大值和紅色最大值是已知的,
所以方程就是 f[i,j](這裡指[1,4]這個區間,所以i=1,j=2)=max(f[i,j-1](指[1,2]這個區間,所以i=1,j-1=1) ,f[i+2j
-1,j-1](指[3,4]這個區間,所以i=1+21=3 j-1=1))
可能不好理解,j可以抽象為[1,4] 4個數, j-1 就為2個數 ,已知 2 個連續的 2個數的區間 那麼就能求出1個 4個數的區間
大概**:
for i=1 -->n如果你問為什麼j放外迴圈,那就是對rmq還不夠理解。f[i,
0]=a[i]; //初始化
for j=1 -->log2(n)
for i=1 -->n
f[i,j]=max(f[i,j-1],f[i+(1
<< (j-1
))]);// rmq狀態轉移方程
如果j放了內迴圈,那麼求解順序就變成了 f[1..n,1]...f[1..n,log2(n)] 這樣就不會先求出 2 個連續的 2個數的區間的最大值,也就不能dp了。
上面講完了rmq的dp之後捏,會發現還缺了乙個步驟,預處理完當然是查詢辣~
我萌已經預處理出了 f[i,j] 表示 原陣列a 中從 下標為 i 開始之後的 2j 個數中的最大值。
也許很抽象,還是舉個栗子。
比如1 -2 9 10 15 38 -9 (我會跟你說這是上面的栗子是因為我想不出栗子了麼)
辣麼 f[1,1] 就是代表 [1,2] 這個區間的最大值 也就是 f[1,1]=1。
f[1,2] 就是代表 [1,4] 這個區間的最大值 也就是 f[1,2]=10。
辣麼 f 陣列所代表的含義應該很清楚了吧...所以腫麼查詢
我萌需要找到兩個區間,而這兩個區間合起來後能包含整個查詢區間而且不包含除查詢區間的數。
還是上面辣個栗子
比如查詢 區間 [2,6] 要腫麼查詢,我萌就找兩個區間, [2,5] 和 [3,6]這兩個區間
因為是查詢最大值所以就是兩個區間有交集也沒什麼關係。
辣麼問題來了,為什麼是這兩個區間而不是其他的兩個區間捏。
為了能把區間用 f[i,j] 的方式表示出了,我萌可以發現 區間 [2,5] 實際上就是 區間 [2,2+22
-1] 辣麼這個區間的最大值就可以用 f[2,2] 表示
同樣的 區間 [3,6] 也可以表示成 f[i,j] 為 f[3,2] 這樣只需要o(1) 就查詢好了
辣怎麼去找這兩個區間?簡單理解是這樣的,因為要包含查詢區間又不允許包含除查詢區間的數。所以這兩個區間必然是這樣的 (設查詢區間 [l,r] )
[l,x] [r-(x-l),r] 可以說這個 x值只要滿足 (l<=x<=r)且(x>=(r-l)/2) 就可以,但是為了滿足 f[i,j] 就必須保證 (x-l+1) 為2的 k (k為自然數)次方(不理解的話拿上面的栗子算一下)
所以用log2 就能找到乙個k值, k=log2(r-l+1) (取整) (r-l+1)是查詢區間的長度,log2後就得到了必然滿足 (x-l+1) 為2的某次方的條件。
辣麼就可以用k來表示 f 陣列了 兩個區間 的最大值為 f[l,k] 和 f[r-2k+1,r] 所以ans=max(f[l,k],f[r-2k+1,r])。
最後,也許你會有點奇怪...為什麼非得用2j的來表示f陣列。我覺得兩個原因吧。
一是dp的需要,用2j表示就可以在o(1)的時間裡進行比較,因為只要比較兩個區間,而3j需要比較三個區間。(也許我瞎bb其實也不是很清楚)
二是可以利用電腦二進位制的屬性,利用位運算更快的求出2j的值。
大概就講這麼多,希望有幫助。
rmq應用還是不多,也就大概是lca ,建議學的是思路.
上次留下的大坑啊...過了將近半年才回來補...
RMQ問題與LCA問題
一 區間最小 最大查詢 range minimum maximum query rmq 問題 toj 2762 描述 已知長度為l 的數列a 詢問區間 l,r 中的最值。若詢問的次數較少,可以用線性的複雜度來查詢,但如果詢問的次數過多且l 過大,那麼複雜度就會很高。所以需要更快速的查詢方法。st 演...
RMQ問題 ST演算法
rmq問題 rmq問題是指求區間最值的問題。rmq演算法 st演算法 時間複雜度 預處理o nlogn 查詢o 1 以求最大值為例,設d i,j 表示 i,i 2 j 1 這個區間內的最大值,那麼在詢問到 a,b 區間的最大值時答案就是max d a,k d b 2 k 1,k 其中k是滿足2 k ...
RMQ問題 Sparse Table演算法
rmq引子 我們都知道求乙個陣列的最小值,可以用很樸素的o n 級別的演算法來求解。那麼,如果現在是求乙個陣列的任意連續子陣列的最小值呢?假設詢問q次,那麼總的時間複雜度為o q n 時間開銷很高!這就是今天所要介紹的rmq問題 range minimum query 然而,如果使用一些分治的思想,...