LCA轉化RMQ(內附RMQ算法ST)

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]);//返回區間最小值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章