//初始化
init_rmq
//max[i][j]中存的是重j開始的2^i個資料中的最大值,最小值類似,num中存有陣列的值
for i : 1 to n
max[0][i] = num[i]
for i : 1 to log(n)/log(2)
for j : 1 to (n+1-2^i)
max[i][j] = max(max[i-1][j], max[i-1][j+2^(i-1)]
//查詢
rmq(i, j)
k = log(j-i+1) / log(2)
return max(max[k][i], max[k][j-2^k+1])
當然,該問題也可以用線段樹(也叫區間樹)解決,演算法複雜度為:o(n)~o(logn),具體可閱讀這篇文章:《資料結構之線段樹》
lca(u)
checked[u]=true
對於每個(u,v)屬於p // (u,v)是被詢問的點對}}
根據實現演算法可以看出,只有當某一棵子樹全部遍歷處理完成後,才將該子樹的根節點標記為黑色(初始化是白色),假設程式按上面的樹形結構進行遍歷,首先從節點1開始,然後遞迴處理根為2的子樹,當子樹2處理完畢後,節點2, 5, 6均為黑色;接著要回溯處理3子樹,首先被染黑的是節點7(因為節點7作為葉子不用深搜,直接處理),接著節點7就會檢視所有詢問(7, x)的節點對,假如存在(7, 5),因為節點5已經被染黑,所以就可以斷定(7, 5)的最近公共祖先就是find(5).ancestor,即節點1(因為2子樹處理完畢後,子樹2和節點1進行了union,find(5)返回了合併後的樹的根1,此時樹根的ancestor的值就是1)。有人會問如果沒有(7, 5),而是有(5, 7)詢問對怎麼處理呢? 我們可以在程式初始化的時候做個技巧,將詢問對(a, b)和(b, a)全部儲存,這樣就能保證完整性。
4、 總結
lca和rmq問題是兩個非常基本的問題,很多複雜的問題都可以轉化這兩個問題解決,這兩個問題在acm程式設計競賽中遇到的尤其多。這兩個問題的解決方法中用到很多非常基本的資料結構和演算法,包括並查集,深度優先遍歷,動態規劃等。
演算法之LCA與RMQ問題
1 概述 lca least common ancestors 即最近公共祖先,是指這樣乙個問題 在有根樹中,找出某兩個結點u和v最近的公共祖先 另一種說法,離樹根最遠的公共祖先 rmq range minimum maximum query 即區間最值查詢,是指這樣乙個問題 對於長度為n的數列a,...
RMQ問題與LCA問題
一 區間最小 最大查詢 range minimum maximum query rmq 問題 toj 2762 描述 已知長度為l 的數列a 詢問區間 l,r 中的最值。若詢問的次數較少,可以用線性的複雜度來查詢,但如果詢問的次數過多且l 過大,那麼複雜度就會很高。所以需要更快速的查詢方法。st 演...
LCA與RMQ的相互轉換
一 最近公共祖先 leastcommon ancestors 對於有根樹t的兩個結點u v,最近公共祖先lca t,u,v 表示乙個結點x,滿足x是u v的祖先且x的深度盡可能大。另一種理解方式是把t理解為乙個無向無環圖,而lca t,u,v 即u到v的最短路上深度最小的點。這裡給出乙個lca的例子...