參照大佬博客:https://www.cnblogs.com/yoke/p/6949838.html
RMQ(Range Minimum/Maximum Query), 是一種問題,即 查詢給定區間的最大值或最小值。
ST算法可在線處理RMQ問題,主要分爲兩步, 初始化 和 查詢。
ST算法的思想是將一個區間平均分成兩個子區間,分別查詢兩個子區間的最值,再求這兩個最值的最值。因此是DP的思想。
F[i,j] 代表以con[i]爲區間左值,長度爲 2^j 的區間的最大(小)值。
初始化:
DP初始狀態爲
for(int i = 0; i < n; i++) F[i,0] = con[i]; // 此時的最值是他本身
狀態轉移方程爲
void RMQ(int num) //預處理->O(nlogn) { for(int j = 1; j < 20; ++j) // 這裏j的範圍根據具體題目數據定義 for(int i = 1; i <= num; ++i) // num爲數組內整數的個數 if(i + (1 << j) - 1 <= num) { maxsum[i][j] = max(maxsum[i][j - 1], maxsum[i + (1 << (j - 1))][j - 1]); minsum[i][j] = min(minsum[i][j - 1], minsum[i + (1 << (j - 1))][j - 1]); } }
注意只有長度爲2^(j - 1)的區間最值查詢出來後,纔可以查詢長度爲 2^j 的區間,因此代碼中兩個for循環的位置不可交換。
查詢爲
RMQ(A, i, j)=max{F[i , k], F[ j - 2 ^ k + 1, k]}。
爲什麼第二個子區間是從j減,因爲允許分成的兩個子區間有重疊的部分(解決了有的區間不能分成兩個互不重疊的 長度爲 2^j 的區間的問題 )。