RMQ演算法詳解

2021-09-10 01:45:05 字數 1933 閱讀 4557

下面我們從乙個實際問題來解釋rmq

我們假設陣列arr為:1,3,6,7,4,2,5

我們設二維陣列dp[i][j]表示從第i位開始連續2^j個數中的最小值。例如dp[2][1]就表示從第二位數開始連續兩個數的最小值(也就是從第二位數到第三位數的最小值),即3,6中的最小值,所以dp[2][1] = 3;

其實我們求 dp[i][j] 的時候可以把它分成兩部分,第一部分是從 i 到 i + 2 ^( j-1 ) - 1 ,第二部分從 i + 2 ^( j-1 ) 到i + 2^j -1 ,為什麼可以這麼分呢?其實我們都知道二進位制數前乙個數是後乙個的兩倍,那麼可以把 i ~ i + 2^j -1 這個區間 通過2^(j-1) 分成相等的兩部分, 那麼轉移方程很容易就寫出來了。(dp[i][0]就表示本身)

dp[i][j] = min(dp [i][j - 1], dp [i + (1 << j - 1)][j - 1])

void rmqinit()

}}

這裡需要注意乙個迴圈變數的順序,我們看到外層迴圈變數為j,內層迴圈變數為i,這是為什麼呢?可以互換一下位置嗎?

答案當然是不可以,我們要理解這個狀態轉移方程的意義,這個狀態方程的含義是:先更新每兩個元素中的最小值,然後通過每兩個元素的最小值獲得每4個元素中的最小值,依次類推更新所有長度的最小值。

而如果是i在外,j在內的話,我們更新的順序就變成了從1開始的前1個元素,前2個元素,前4個元素,前8個元素。。。

當j等於3的時候dp[1][3] = min(min(ans[0],ans[1],ans[2],ans[3]),min(ans[4],ans[5],ans[6],ans[7]))的值,

但是我們根本沒有計算min(ans[0],ans[1],ans[2],ans[3])和min(ans[4],ans[5],ans[6],ans[7]),所以這樣的方法肯定是錯誤的。

為了避免這樣的錯誤,一定要好好理解這個狀態轉移方程所代表的含義。

接下來我們來講解rmq的查詢部分,假設我們需要查詢區間[l ,r]中的最小值,令k = log2(r - l + 1); 則區間[l, r]的最小值rmq[l,r] = min(dp[l][k], dp[r - (1 << k) + 1][k]);

但是為什麼這樣就可以保證是區間最小值了呢?

mn[l][k]維護的是[l, l + 2 ^ k - 1], mn[r - (1 << k) + 1][k]維護的是[r - 2 ^ k + 1, r] 。

那麼只要我們保證r - 2 ^ k + 1 <= l + 2 ^ k - 1就能保證rmq[l,r] = min(dp[l][k], dp[r - (1 << k) + 1][k]);

接下來我們用分析法來證明這個不等式:

我們假設 r - 2^k +1 <= l + 2^k -1 這個等式成立

即有 r - l + 2 <= 2^(k+1) 也就是 r - l + 2 <= 2 * 2^k

又因為 k =log2 (r- l + 1);

那麼 r - l + 2 <= 2 * (r - l +1)

則 r - l + 2 <= 2*(r - l) + 2

所以 r - l >= 0 所以假設成立

我們舉個栗子 l = 4,r = 6;

我們假設陣列arr為:1,3,6,7,4,2,5

此時 k = log2( r - l + 1)= log2(3)=1

則dp[4][6] = min(dp[4][1],dp[5][1])

dp[4][1] = 4,dp[5][1] = 2,所以dp[4][6] = min(dp[4][1],dp[5][1]) = 2

我們很容易看出來答案是正確的。

int getrmq(int x, int y)

rmq演算法詳解 模板

rmq range minimum maximum query 問題是指 對於長度為n的數列a,回答若干詢問rmq a,i,j i,j n 返回數列a中下標在 i,j 裡的最小 大 值,也就是說,rmq問題是指求區間最值的問題 主要方法及複雜度 處理複雜度和查詢複雜度 如下 1.樸素 即搜尋 o n...

再談RMQ演算法

大家知道rmq演算法就是求乙個區間裡的任意區間的最大值和最小值的高效演算法,因為只需要乙個預處理就可以在o 1 的時間裡算出任意區間的最值。所以當遇到在乙個區間裡求最值之差不超過某乙個數的最長子區間問題就可以利用該方法,當然還需要用到二分演算法。舉個例子 在8,4,2,4,3,2,4,5,2,6這個...

RMQ演算法總結

給定乙個陣列,查詢陣列給定範圍內的最值。void rmq int num 預處理 o nlogn 演算法主體 for int j 1 j 20 j for int i 1 i num i if i 1 j 1 num maxsum i j max maxsum i j 1 maxsum i 1 j ...