ST演算法解決RMQ問題

2021-09-10 02:28:03 字數 1338 閱讀 8016

簡單說就是求區間最值問題,若是簡單的單次詢問或者是區間長度很短的詢問,可以用暴力的方法來實現,但面對大資料的時候此方法必然超時,這裡介紹o(nlogn)預處理,o(1)查詢的st演算法。

st的高效在於o(nlogn)的時間預處理,o(1)的時間來查詢。其主要思想就是將所求的區間化為兩個小區間,這兩個區間的長度正好是2的k次冪,總長度正好覆蓋[l,r],得到的結果就是所求答案。

首先要清楚為什麼是分成兩段,而不是3段,4段,首先分成兩段的話是好寫的,比那些處理3段以及n段畢竟簡單。在logn的時間複雜度下,以2為底或者以其他數為底的話,時間複雜度差距也不是那麼明顯,所以選擇了分成兩段,便於位運算以及其他方面的簡便操作。

首先確定dp[i,j]表示以第i個數開始,長度為2^j的區間長度的區間最值。

易知dp[i][0] = s[i].即表示以i為起點,長度為1的區間的最值就是當前的數值。

然後可以考慮從當前乙個點,以2的指數倍向一側擴充套件,可以得到以當前點為起點,延申到邊界的陣列最值。

考慮o(nlogn)的時間複雜度,即以當前點為起始點,向右側開始維護最值,從2^1開始,因為2^k一定是偶數,所以一定可以將2^k拆分為兩個2^(k-1),即將區間[l,r]分為[l,l+2^(k-1)-1]跟[l+2^(k-1),r],將區間長度從小到大開始列舉,這樣一定可以得到以當前起點一直到n的的每乙個區間段內的最大值。

ll maxx[n][20],minn[n][20],n,s[n];

void init()

}

對於當前區間[l,r],如何表示為以某個點為起點,長度是2^k的區間。

k=[log2(j-i+1)],則有:rmq(i, j) = max(dp[i,k], dp[j-2^k+1,k])。

考慮k的取值問題,k一定可以將整個區間都覆蓋嗎?

[l,r]分成2份,一部分是[l,i+2^(k-1)-1],一部分是[j-2^(k-1)+1,r],若是要完成覆蓋,則應該有j-2^(k-1)+1 <= i+2^(k-1)-1,移項合併同類項得到2^k >= j-i+1,可以驗證上述k取值是成立的。

分成兩個區間後,在兩個區間取最值就可以了。

ll rmq_min(ll l,ll r)

ll fpow(ll n,ll k)return r;}

ll maxx[n][20],minn[n][20],n,s[n];

void init()

}ll rmq_min(ll l,ll r)

ll rmq_max(ll l,ll r)

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