rmq-st算法
轉自:http://dongxicheng.org/structure/lca-rmq/
該算法一般用較長的時間做預處理,待信息充足以后便可以用較少的時間回答每個查詢。ST(Sparse Table)算法是一個非常有名的在線處理RMQ問題的算法,它可以在O(nlogn)時間內進行預處理,然后在O(1)時間內回答每個查詢。
首先是預處理,用動態規劃(DP)解決。設A[i]是要求區間最值的數列,F[i, j]表示從第i個數起連續2^j個數中的最大值。例如數列3 2 4 5 6 8 1 2 9 7,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]平均分成兩段(因為f[i,j]一定是偶數個數字),從i到i+2^(j-1)-1為一段,i+2^(j-1)到i+2^j-1為一段(長度都為2^(j-1))。用上例說明,當i=1,j=3時就是3,2,4,5 和 6,8,1,2這兩段。F[i,j]就是這兩段的最大值中的最大值。于是我們得到了動態規劃方程F[i, j]=max(F[i,j-1], F[i + 2^(j-1),j-1])。
然后是查詢。取k=[log2(j-i+1)],則有:RMQ(A, i, j)=min{F[i,k],F[j-2^k+1,k]}。 舉例說明,要求區間[2,8]的最大值,就要把它分成[2,5]和[5,8]兩個區間,因為這兩個區間的最大值我們可以直接由f[2,2]和f[5,2]得到。
偽代碼
//初始化
?
INIT_RMQ
?
//max[i][j]中存的是重j開始的2^i個數據中的最大值,最小值類似,num中存有數組的值
?
for i : 1 to n
?
? max[0][i] = num[i]
?
for i : 1 to log(n)/log(2)
?
? for j : 1 to (n+1-2^i)
?
? ? ?max[i][j] = MAX(max[i-1][j], max[i-1][j+2^(i-1)]//預處理階段,算出所有從j開始到j+2^(i-1)-1區域的最大值,即max[i][j]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//max[i][j]的值由兩部分得出:[j,j+2^(i-1)-1]和[j+2^(i-1),j+2^(i-1) + 2^(i-1)-1]
?
//查詢
?
RMQ(i, j)
?
k = log(j-i+1) / log(2)
?
return MAX(max[k][i], max[k][j-2^k+1])//肯會保證區域[i,i+2^k-1]和[j-2^k+1,j-2^k+1+2^k -1]這兩個區域,也就是[i,i+2^k-1]和[j-2^k+1,j]這兩個區域覆蓋區域[i,j],也就是說i+2^k-1>=j-2^k+1
總結
- 上一篇: lca---tarjan算法
- 下一篇: 中位数求解