RMQ (Range Minimum/Maximum Query)問題是指:對於長度爲n的數列A,回答若干詢問RMQ(A,i,j)(i,j<=n),返回數列A中下標在i,j裏的最小(大)值,也就是說,RMQ問題是指求區間最值的問題。
如果對一顆樹進行dfs遍歷 按照遍歷的順序將結點深度和標號寫入一個數組d
並記錄每個結點被第一次被訪問時在d中的位置
如圖 則d中的深度如下
1234343232343212
對應的標號如下
1247484252696213
對於結點7 和9 他們的lca就是 深度區間裏最小的那個 也就是2 對應着點2
現在來看RMQ的解決方法:
RMQ問題:區間最小值問題(也可以解決區間最大值問題)
解決算法:ST (Sparse - Table算法,基於動態規劃求區間最值的算法)
ST算法分爲預處理和查詢兩部分
首先定義數組:我們用定義 Amax[i][j] 爲從 i開始的,長度爲2^j的區間裏面的最大值, Amin[i][j]爲從i開始,長度爲2^j的區間裏面的最小值
一:預處理如下
我們可以將一段長度爲2^j的區間分成兩段長度都爲2^(j-1)的相同區間
區間1 爲 i.....i+2^(j-1)-1 區間2爲 i+2^(j-1).....i+2^j-1
得到狀態轉移方程(由長度遞增推出)
Amax[i][j] = max(Amax[i][j-1], Amax[i+2^(j-1)][j-1])
Amin[i][j] = max(Amin[i][j-1], Amin[i+2^(j-1)][j-1])邊界條件爲F[i][0]=A[i].
二:查詢如下
MAX L R 表示要查詢[L, R]區間的最大值
MIN L R 表示要查詢[L, R]區間的最小值
我們需要找到這樣一個k值,使得從L開頭的一個長度爲2^k的區間 和 以R結尾的長度爲2^k的區間 包括了整個[L, R]
k值計算有兩種方案 1,k =(int) log2( R-L+1) 2,k值從0開始遞增 直到2^k大於 R-L+1 爲止。
找到k後,查詢操作有
return max(Amax[L][k], Amax[R-(1<<k)+1][k]);//返回區間最大值
return min(Amin[L][k], Amin[R-(1<<k)+1][k]);//返回區間最小值