想學習一下lca倍增,先 水乙個黃題 學一下st表
這是乙個運用倍增思想,通過動態規劃來計算區間最值的演算法
求出區間最值求出區間最值:回答詢問
用 \(f[i][j]\) 來儲存從第 \(j\) 個點開始,向後 \(2 ^ i - 1\) 個點(共 \(2 ^ i\) 個點)中的最值(包括本身)
利用二分法的思想,將區間 \([ j, ~j + 2 ^ i- 1 ]\) 平均(大概)分成兩半
可以算出,區間 \([ j, ~j + 2 ^ i - 1 ]\) 的長度為 \(2 ^ i\)
所以一半的長度為 \(2 ^ \)
那麼分成的兩個區間就為 \([j, ~j + 2 ^ - 1 ]\) 和 \([ j + 2 ^ , ~j + 2 ^ i - 1 ]\) 。
毫無疑問,
\[f[i][j] = max(f[i - 1][j],~f[i - 1][j + (1 << i - 1)])
\]這樣遞推式就出來了
現在來想一下:
\(f[0][j]\) 就是從 \(j\) 開始向後數第 \(2 ^ 0 - 1\) 個點的最值,區間為 \([j,~j]\)(區間不能這麼寫,這裡請不要較真)
不用考慮,\(f[0][j]\) 就是第 \(j\) 個數本身
好了,現在邊界也得出來了,可以開始 dp 了
上**:
void prew()
}
乙個小問題:
由於 \(log_2\) 運算可能會出現實數,而我們又用整數型別來儲存,所以可能會出現兩個區間不能完全覆蓋整個區間的情況,得出的 \(f[i][j]\) 不夠精準
最簡單的方法就是用兩個區間覆蓋
反正又沒要求兩個區間不能重疊~~
可以選用 \(f[k][l]\) 和 \(f[k][r-(1《來覆蓋 \(f[l][r]\)
所以 $$f[l][r] = max(f[k][l],f[k][r -(1 << k)+ 1])$$(\(k\) 為區間 \([l,~r]\) 的長度的 \(log_2\))
再上**:
int ask(int l, int r)
#include #include #include #include #include #define maxn 100010
#define int long long
using namespace std;
//-------------定義結構體-----------
//--------------定義變數------------
int f[31][maxn], log2[maxn], a[maxn]; // f[i][j]表示從 j 往後 2 ^ i - 1 個數中的最大值
int n, m;
//--------------定義函式------------
inline int read()
int max(int a, int b)
int min(int a, int b)
void swap(int &a, int &b)
void pre()
}int ask(int l, int r)
//---------------主函式-------------
signed main()
return 0;
}
模板題:
洛谷p3865
ST(稀疏表)演算法
作用 st演算法是用來求解給定區間rmq的最值,本文以最小值為例 舉例 給出一陣列a 0 5 則區間 2,5 之間的最值為1。1 離線預處理 運用dp思想,用於求解區間最值,並儲存到乙個二維陣列中。具體解釋 1 離線預處理 st演算法使用dp思想求解區間最值,貌似屬於區間動態規劃,不過區間在增加時,...
st 表演算法模板
借鑑於 st表是基於二分的思想,st i j 表示j到j 2 n 1區間內的最值,長度為2 n 構建的時候用二分構建,那麼st i j 如何用其他狀態來繼承呢?j到j 2 i 1的長度為2 i,那麼一半的長度就等於2 i 1 那麼前半段的狀態表示為st i 1 j 後半段的長度也為2 i 1 起始位...
RMQ演算法 ST表
題目大意就是給你兩個長度為n的序列讓你找到乙個盡可能大的下標p使得1 p之間的任意兩個區間l r都滿足rmq u,l,r 相等其實就是最小下標相同 rmq range minimum maximum query 問題是指 對於長度為n的數列a,回答若干詢問rmq a,i,j i,j n 返回數列a中...