求解區間最值的ST演算法

2021-06-17 21:40:41 字數 2226 閱讀 4352

作用:st演算法是用來求解給定區間rmq的最值,本文以最小值為例

舉例:給出一陣列a[0~5] = ,則區間[2,5]之間的最值為1。

(1)離線預處理:運用dp思想,用於求解區間最值,並儲存到乙個二維陣列中。

具體解釋:

(1)離線預處理:

st演算法使用dp思想求解區間最值,貌似屬於區間動態規劃,不過區間在增加時,每次並不是增加乙個長度,而是使用倍增的思想,每次增加2^i個長度。

使用f[i,j]表示以i為起點,區間長度為2^j的區間最值,此時區間為[i,i + 2^j - 1]。

比如,f[0,2]表示區間[0,3]的最小值,即等於4,f[2,2]表示區間[2,5]的最小值,即等於1。

在求解f[i,j]時,st演算法是先對長度為2^j的區間[i,i + 2^j - 1]分成兩等份,每份長度均為2^(j - 1)。之後在分別求解這兩個區間的最值f[i,j - 1]和f[i + 2^(j - 1),j - 1]。,最後在結合這兩個區間的最值,求出整個區間的最值。特殊情況,當j = 0時,區間長度等於0,即區間中只有乙個元素,此時f[i,0]應等於每乙個元素的值。

舉例:要求解f[1,2]的值,即求解區間[1,4] = 的最小值,此時需要把這個區間分成兩個等長的區間,即為[1,2]和[3,4],之後分別求解這兩個區間的最小值。此時這兩個區間最小值分別對應著f[1,1] 和 f[3,1]的值。

狀態轉移方程是 f[i,j] = min(f[i,j - 1],f[i + 2^(j - 1),j - 1])

初始狀態為:f[i,0] = a[i]。

在根據狀態轉移方程遞推時,是對每一元素,先求區間長度為1的區間最值,之後再求區間長度為2的區間最值,之後再求區間長度為4的區間最值....,最後,對每乙個元素,在求解區間長度為log2^n的區間最值後,演算法結束,其中n表示元素個數。

即:先求f[0][1],f[1][1],f[2][1],f[3][1],,,f[n][1],再求.f[0][2],f[1][2],f[2][2],f[3][2],,,f[m][2],... 。

在預處理期間,每乙個狀態對應的區間長度都為2^i。由於給出的待查詢區間長度不一定恰好為2^i,因此我們應對待查詢的區間進行處理。

這裡我們把待查詢的區間分成兩個小區間,這兩個小區間滿足兩個條件:(1)這兩個小區間要能覆蓋整個區間(2)為了利用預處理的結果,要求小區間長度相等且都為2^i。注意兩個小區間可能重疊。

如:待查詢的區間為[3,11],先盡量等分兩個區間,則先設定為[3,7]和[8,11]。之後再擴大這兩個區間,讓其長度都等於為2^i。剛劃分的兩個區間長度分別為5和4,之後繼續增加區間長度,直到其成為2^i。此時滿足兩個條件的最小區間長度為8,此時i = 3。

在程式計算求解區間長度時,並沒有那麼麻煩,我們可以直接得到i,即等於直接對區間長度取以2為底的對數。這裡,對於區間[3,11],其分解的區間長度為int(log(11 - 3 + 1)) = 3,這裡log是以2為底的。

根據上述思想,可以把待查詢區間[x,y]分成兩個小區間[x,x + 2^i - 1] 和 [y - 2^i + 1,y] ,其又分別對應著f[x,i]和f[y - 2^i + 1,i],此時為了求解整個區間的最小值,我們只需求這兩個值得最小值即可,此時複雜度是o(1)。

**:

#include #include using namespace std;

/*方程

f[i,j]:區間[i,i + 2^j - 1]的最小值,此時區間長度為2^j

f[i,j] = min(f[i,j - 1],f[i + 2^(j - 1),j - 1])

f[i,0] = narr[i];*/

int f[1000000][20];//待比較元素的個數最大為1百萬

void sparsetable(int narr,int nlen)

//遞推

int nlog = int(log(double(nlen))/log(2.0));

for (int j = 1;j <= nlog;j++)

} }}

int rmq(int narr,int nlen,int nstart,int nend)

int main()

; sparsetable(narr,6);

cout<

ST表演算法(求解區間最值)

如下 bin 0 1 for int i 1 i 20 i bin i bin i 1 2 bin i 表示2的i次方 log 0 1 for int i 1 i 200000 i log i log i 2 1 log i 表示log i for int i 1 i n i mn 0 i a i ...

st演算法模板(區間最值)

f 1,0 表示第1個數起,長度為2 0 1的最大值,其實就是3這個數。f 1,2 5,f 1,3 8,f 2,0 2,f 2,1 4 從這裡可以看出f i,0 其實就等於a i 這樣,dp的狀態 初值都已經有了,剩下的就是狀態轉移方程。我們把f i,j j 1 平均分成兩段 因為j 1時,f i,...

ST演算法 區間最值問題 C 實現

區間最值 void st prework vector int a,int n 當查詢任意區間 l,r 的最值時,我們先計算出乙個k,滿足2 k r 1 2k 1,也就是使2的k次冪小於區間長度的前提下最大的k。那麼 從l開始的2k個數 和 以r結尾的2 k個數 這兩段一定覆蓋了整個區間 l,r 這...