rmq (range minimum/maximum query)問題是指:對於長度為n的數列a,回答若干詢問rmq(a,i,j)(i,j<=n),返回數列a中下標在i,j裡的最小(大)值,也就是說,rmq問題是指求區間最值的問題。樸素解法不再贅述了,非常非常暴力,理論上是不會有比賽能讓你用樸素演算法求解的。思路非常簡單,遍歷就完事了,當然也是非常慢的一種演算法。
st演算法本質上是動態規劃的思想,狀態定義為:f(i,j),從第i個數起連續2^j個數中的最大值。那麼st演算法就分為2步:
1.在o(nlogn)的時間複雜度內構造出dp陣列。
2.進行查詢。
首先,狀態的定義上面已經給出了:f(i,j),從第i個數起連續2^j個數中的最大值。假設有原序列a[i],那麼可以得到初始值:dp[i][0] = a[i]。
狀態轉移方程為:
dp(i,j) = max(dp[i,j-1],dp[i + 2^(j-1),j-1]);
實際上,這樣是把dp(i,j)這個狀態給平均分成了2部分。如果我們假設序列a[i],i=8。那麼我們可以得到i = 1,j = 3。(總長度為8,那麼i = 1是從第乙個數起,要連續2^j個數,即log2n = j,n = 8,即j = 3)將i = 1、j = 3代入轉移方程,可以得到恰好是[1,4]與[5,8],平分了[1,8]。所以有**:
void st(int n)
for(int j = 1;(1 << j) <= n;j++)
}}
這裡參考了大佬的寫法,我之前的寫法就是很簡單的寫法,沒有用位運算,這裡給不會位運算的同學解釋一下:1 << j,就是1向左移j位,二進位制的數每向左移1位就*2,那麼移動j位實際上就是2^j了。這裡的2個for迴圈都是為了防止超出範圍。
可以看到,上面的求法得到的dp陣列不是完全區間覆蓋,不能直接查詢區間。在區間[1,8]中,能直接得到答案的區間只有[1,1]、[1,2]、[1,4]、[1,8]、[2,2]..以此類推。那麼我們仍然分開考慮,這裡令k = log2( j - i + 1),則有:
ans(i, j) = max
這裡也是,之前對於k值的計算是直接算的,某大佬利用while迴圈,因為k值要求是int型別,所以迴圈結束獲得的就是k值。
將所有max函式更換成min函式就是從最大值變成最小值了,很簡單也很容易理解。
poj-3264 balanced lineup
基本是模板題了。
RMQ問題(ST表解法)
針對 範圍最值問題。對於陣列a 1 n 有操作如下 rmq l,r a中第l個數到第r個數中的最小值 最大值模擬 d i j 從i開始,長度為2j 的一段元素的最小值。可推 d i j min d i j 1 d i 1 j 1 j 1 查詢時,令k為滿足2k r l 1的最大整數,由於求最小值可重...
RMQ問題 ST演算法
rmq問題 rmq問題是指求區間最值的問題。rmq演算法 st演算法 時間複雜度 預處理o nlogn 查詢o 1 以求最大值為例,設d i,j 表示 i,i 2 j 1 這個區間內的最大值,那麼在詢問到 a,b 區間的最大值時答案就是max d a,k d b 2 k 1,k 其中k是滿足2 k ...
RMQ問題的ST演算法
st sparse table 演算法的基本思想是,預先計算從起點a i 開始長度為2的j次方 j 0,1.logn 的區間的最小值,然後在查詢時將任何乙個區間a i.j 劃分為兩個預處理好的可能重疊的區間,取這兩個重疊區間的最小值。在預處理階段,從起點a i 開始,任何乙個長度為2 j的區間都可以...