rmq問題:求長度為n的數列中,求[i,j]直接的最值。
st演算法:一種動態規劃的方法。
一、預處理dp陣列
對於區間[i,i+2^j-1]的最值,只需要知道區間[i,i+2^(j-1)-1]和區間[i+2^(j-1),i+2^j-1]的最值即可。
由此可的遞推方程:dp[i,i+2^j-1] = max(dp[i,i+2^(j-1)-1],dp[i+2^(j-1),i+2^j-1])
但是對於乙個比較長的數列,2^j是乙個非常大的數,我們也可發現,沒什麼必要直接記錄左右端點。
優化為i記錄乙個起點,j記錄類似距離的東西,dp[i,j]表示區間[i,i+2^j-1]。
優化後遞推方程:dp[i,j] = max(dp[i,j-1],dp[i+2^(j-1),j-1])
預處理dp陣列時間複雜度為o(nlogn)。
二、查詢最值
所以開始把乙個區間當dp陣列求出來,再進行查詢即可。
但是查詢時候,知道的是兩個端點l,r。
對於區間[l,r],如何再dp陣列中查詢呢?
前面講了i表示起點,j代表類似距離的東西。
很明顯l就是i了。可是2^j-1不可能是r,這時候就要找個中間的"j"了。
令len = r-l+1, 則2^k <= len(此處注意不是2^k-1,反證:當2^k-1 == len時,l + 2^k-1 = l + len = r + 1 > r)
即[l,r] = max(dp[l,k],dp[r-(2^k)+1,k])
查詢時間複雜度為o(1)。
儘管**比較簡潔並且功能比較強大,速度也比較快,可是並沒有線段樹那麼功能多。
1 #include 2 #include 3 #include 4st演算法using
namespace
std;
5const
int maxn = 100005;6
int ma[maxn][20];7
int mi[maxn][20];8
inta[maxn];
9void init(int
n)17}18
int rmq_max(int l, int r, int
k)21
int rmq_min(int l, int r, int
k)24
int rmq(int l, int
r)32
intmain()
42return0;
43 }
RMQ問題之ST演算法
st演算法 st演算法是用於解決rmq問題 區間最值問題 的一種強有力的工具。o nlogn 預處理,o 1 查詢最值,利用的是倍增的思想。但 但是,使用st演算法的條件是沒有修改操作,emmm 演算法流程 最大值為例 預處理 用f i j 表示,從i位置開始的2 j 個數中的最大值,例如f i j...
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的區間都可以...