演算法 ST表

2022-04-10 03:36:04 字數 1834 閱讀 4772

想學習一下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中...