一、區間最小/ 最大查詢(range minimum/maximum query) :rmq 問題
//toj: 2762
[ 描述] 已知長度為l 的數列a ,詢問區間[l, r] 中的最值。
若詢問的次數較少,可以用線性的複雜度來查詢,但如果詢問的次數過多且l 過大,那麼複雜度就會很高。所以需要更快速的查詢方法。
st 演算法:預處理o(nlogn) ,查詢指定區間的最值o(1)
把待求區間[l, r] 分為兩段長為len 的區間,左邊一段為[l, l+len-1] ,右邊一段為[r-len+1, r] ,len 必須使得兩段區間覆蓋待求區間。
設所求陣列為w :
那麼,所求最小值就是兩個區間的最小值的最小值:
即min(min, min)
若都在預先處理中先求得兩個區間的最小值,則每次查詢的複雜度都是o(1) 。
預處理:(dp )
設dp[i][j] 表示從第i 個數起連續2^j 個數中的最值。
dp[i][0]=a[i] 1<=i<=n
dp[i][j]=min(dp[i][j-1], dp[i+2^(j-i)][j-1])
求最值:把區間[l, r] 分成兩個長度為2^n 的區間。
為使區間被分解後,長度為2^n ,區間部分可重疊,但不可越過[l, r] 。
例如 [3, 9] à [3, 6]+[6, 9] 即:dp[3, 2] 和dp[6, 2]
注:dmin 與dmax 用前清零。
將rmq 拓展到二維狀況時,依然使用st 演算法先進行預處理,再進行查詢。其中可以有兩種做法(以取最大值為例),對於數字矩陣num[1..m][1..n] ,取其中乙個子矩陣的最大值。第一種方法:dmax[x][y][i][j] 表示對於點(x, y) 為左上點,(x+2^i-1, y+2^j-1) 為右下點的子矩陣的最大值。在詢問時,將待查詢矩陣一分為四取最大值即可。
//toj: 3375
第二種方法:是dmax[x][y][i] 記錄以(x, y) 為左上點,(x+2^i-1, y+2^i-1) 為右下點的正子矩陣的最大值。在詢問時,也需要將待查詢矩陣分為若干正子矩陣,取最大值即可。
第二種方法由於比第一種方法在dmax 上少了乙個維度,所以大大的節省了空間。
一、 最近公共祖先( lowest common ancestors ) :lca 問題
//toj: 3361 1051
對於有根樹t 的兩個結點u 、v ,最近公共祖先lca(t, u, v) 表示乙個結點x ,滿足x 是u 、v 的祖先且x 的深度盡可能大。另一種理解方式是把t 理解為乙個無向無環圖,而lca(t, u, v) 即u 到v 的最短路上深度最小的點。
解決lca 主要是用最經典的tarjan 離線演算法,需要用到並查集來輔助。
1 、在並查集中建立僅包含x 結點的集合,即fa[x]=x;
2 、處理x 的所有孩子,處理完每個孩子後,令fa[ 孩子]=x ,即將孩子和x 所在集合合併;
3 、全部孩子處理完後,將x 標記為處理結束;
4 、處理所有與x 相關的詢問。對於每個詢問lca(x, y) ,若y 已被標記,則記錄下lca(x, y)=find(y) ,即y 所在集合的代表元素。
[ 模板] ( 以3361 為例)
在處理詢問的時候需要建立關聯序列表,另外呼叫lca 時候必須呼叫根結點。
在查詢的時候根據題意修改。
二、 lca 與rmq :
// 資料:rmq 與lca 問題( 郭華陽).ppt
rmq 向lca 轉化:設序列a 的長度為n
1 、設序列中最小值為為ak ,建立優先順序為ak 的根結點tk ;
2 、將a[1..k-1] 遞迴建樹作為tk 的左子樹;
3 、將a[k+1..n] 遞迴建樹作為tk 的右子樹。
rmq(a, i, j) 查詢a[i..j] 的最值即為lca(t, i, j) 。
lca 向rmq 轉化:
對有根樹t 進行dfs ,將遍歷到的結點按照順序記下,得到乙個長度為2*n-1 的序列,稱之為t 的尤拉序列f ,每個結點在尤拉序列中出現,記錄pos[u] 為結點u 在尤拉序列中
第一次出現的位置。
lca(t, u, v)=rmq(b, pos(u), pos(v))
演算法之LCA與RMQ問題
1 概述 lca least common ancestors 即最近公共祖先,是指這樣乙個問題 在有根樹中,找出某兩個結點u和v最近的公共祖先 另一種說法,離樹根最遠的公共祖先 rmq range minimum maximum query 即區間最值查詢,是指這樣乙個問題 對於長度為n的數列a,...
LCA和RMQ問題雜談
首先 mathrm 問題指的是求解樹上兩點的最近公共祖先,mathrm 問題指的是求解數列區間最值。mathrm 問題轉 mathrm 問題應該是人盡皆知了,我們可以先跑出樹的 mathrm 序,使用每次進入或回到節點都記錄一次的那種 mathrm 序,那麼只需記錄每個節點第一次出現位置就可以查詢了...
LCA問題的RMQ解法解析
lca問題是指最近公共祖先問題,rmq問題是只區間最小值問題,我們可以將lca問題轉化為rmq問題,然後利用rmq的解法來解決lca問題。有關rmq問題的詳解可以參考我的部落格,有關於rmq問題的詳解。本部落格重點講如何將lca問題轉化為rmq問題。當我們深度遍歷樹時,我們沒遇到乙個未訪問過的節點就...