rmq(range minimum/maximum query)
,即區間最值問題。
對於長度為n
的數列a
,回答若干查詢rmq(a,i,j)(i,j<=n)
,返回數列a
中下標在i,j
裡的最大(小)值。
假設當前題目要求區間最小值,我們令dp[i][j]
代表從i
開始,長度為\(2^\)這段區間的最小值。
於是便有:\(dp[i][j]=min(dp[i][j-1],dp[i+^][j-1])\)
分析可知,\(dp[i][j-1]\)代表從i
開始,長度為\(2^\)區間一半中的最小值,而 \(dp[i+2^][j-1]\)即為區間的另一半。
即為區間的另一半。
最終(從下往上看):
\(dp[0][*]\)
\(dp[1][*]\)
\(dp[2][*]\)
\(dp[3][*]\)
\(dp[4][*]\)
\(dp[5][*]\)
\(dp[6][*]\)
\(dp[7][*]\)
\(dp[*\)][3]
\(1\)
\(dp[*\)][2]
\(1\)
\(1\)
\(1\)
\(5\)
\(2\)
\(dp[*][1]\)
\(3\)
\(1\)
\(1\)
\(5\)
\(7\)
\(6\)
\(2\)
\(dp[*][0]\)
\(4\)
\(3\)
\(1\)
\(5\)
\(7\)
\(8\)
\(6\)
\(2\)
預處理
根據狀態轉移方程,首先指定當區間長度為\(2^\)時的各初始值,隨後推出後面的結果。
void st_init(const vector&a) \leq r-l+1\)的最大整數,則以l
開頭、以r
結尾的兩個長度為\(2^\)的區間合起來即覆蓋了查詢區間[l,r]
。
int rmq(int l, int r) {
int k=0;
while ((1<
return min(dp[l][k], dp[r-(1嗯!怎麼說呢?感覺線段樹在這種型別的題目中好像是最萬能的方法了。
對於一維中的線段樹,我們想要查詢某個區間的最值,首先就應該建樹咯~(具體方法省略)
而在查詢時,我們可以從根節點向下遞迴搜尋,如下圖,假設查詢區間為[2,6]。
將
[2,6]
這乙個大區間分解為不相交的三個小區間[2,3]、[4,5]、[6]
,而最終的結果便由這三個節點中所維護的資訊決定的!我們假設查詢還是區間最小值,於是最終的結果為\(\min(1,7,6)=1\)
線段樹可以解決普通的
[點/區間] 修改+查詢
,當然它也可以解決樹中的路徑權值 修改+查詢
(樹鏈剖分)。
資料結構專題小結 RMQ問題
範圍最小值問題 range minimum query 是指 給定乙個n個元素的陣列a 1 a 2 a n 設計乙個資料結構,支援查詢操作query l,r 計算min。該問題在實踐中常用tarjan的sparse table演算法。它的預處理時間是o n logn 但查詢只需要o 1 而且常數非常...
資料結構 線段樹實現ST表功能(RMQ問題)
以poj3264為例引入吧。其實還是很基礎的線段樹一種。這裡不用修改,只要建樹 查詢即可了。但是我一開始用c 的輸入輸出流配套io就tle了,換成c的scanf輸入就ac了,還是挺卡時間的吧。但處理區間rmq問題還是推薦st表,因為st表每次查詢就o 1 但線段樹的話,每次查詢的話就是乙個searc...
資料結構 二 RMQ 區間最值查詢
rmq 和普通陣列的區別是 rmq 是二維陣列,維度為 其中 rmq i j rmq i j rmq i j 表示的是從 a i a i a i 開始長度為 2 j2 j 2j的區間的最小值,那麼顯然,它的初始化可以遞迴進行,且複雜度為 o n logn o nlogn o nlog n 當要查詢 ...