RMQ問題與ST演算法

2021-08-22 11:49:01 字數 1179 閱讀 1337

對於問題(rmq,random maximum query):給你一串固定、不修改的數字,詢問多次某個區間內的最大值或者最小值。

用樸素的想法,依次遍歷得到答案,時間複雜度為o(n),但是對於多次詢問,如1e6次詢問,這樣的演算法就不是最優的了。所以出現了st演算法。

st演算法的原理是動態規劃,通過o(logn)的預處理dp陣列,得到o(1)的詢問。

假設dp[i,j]表示從a[i]到a[i+2^j-1]這個範圍內的最大值,即以a[i]為起點連續2^j個數的最大值。

我們把它一分為二,每段元素都為2^(j-1)個數字。也就是說dp[i,j]分為dp[i, j - 1]和f[i + 2^( j - 1), j- 1]兩部分(自己代入一下dp的定義)。

所以我們很容易得到狀態轉一方程dp[i][j] = max(dp[i][j - 1], dp[i + 2^(j-1)][j - 1]);

我們在給dp[i][0]初始化一下均為a[i]。預處理完畢。

先引入乙個k值,每個區間均為2^(k-1)個數字,所以兩部分區間為[i, 2^(k-1) + i -1]和[j - 2^(k-1) + 1,j]。顯然必須要滿足2個子區間能夠完全覆蓋[i , j],即要求(2^(k-1) + i -1) + 1 >= (j - 2^(k-1) +1),易得2^k >= (j - i + 1),取k的最小值,使2個子區間盡可能的短。所以k = log2(j - i + 1);(向下取整)

所以對於每次詢問易得ans = max(dp[i][k],dp[j - 2^k + 1][k])。

cmath中log2函式效率較低,所以可以用遞推處理log2d的值,我們用lo代表log2d向下取整的值,則lo[d] = lo[d/2]+1。

/*

輸入一串數字,給你m個詢問,每次詢問就給你兩個數字x,y,要求你說出x到y這段區間內的最大數。

輸入:輸入n,m。其中n個數字,m次詢問

10 2

3 2 4 5 6 8 1 2 9 7

1 43 8

輸出:58*/

#include using namespace std;

const int n = 1e6 + 5, logn = 20;

int lo[n], dp[n][logn + 5], a[n];

int main()

return 0;

}

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的區間都可以...

RMQ問題的ST演算法

st sparse table 演算法的基本思想是,預先計算從起點a i 開始長度為2的j次方 j 0,1.logn 的區間的最小值,然後在查詢時將任何乙個區間a i.j 劃分為兩個預處理好的可能重疊的區間,取這兩個重疊區間的最小值。在預處理階段,從起點a i 開始,任何乙個長度為2 j的區間都可以...