借助倍增和動態規劃可以實現o(1)的時間複雜度的查詢
預處理:
①區間dp 轉移方程 f[i][j] = min(max同理)(f[i][j - 1],f[i + ][j - 1]) f[i][j]表示從i位置開始的後2^j個數中的最大值
用f[i][j]表示從j到j+2^i-1的最小值(長度顯然為2^i)。
任意一段的最小值顯然等於min(前半段最小值,後半段最小值)。
那麼f[i][j]如何用其他狀態來繼承呢?
j到j+2^i-1的長度為2^i,那麼一半的長度就等於2^(i-1)。
那麼前半段的狀態表示為f[i-1][j]。
後半段的長度也為2^(i-1),起始位置為j+2^(i-1)。
那麼後半段的狀態表示為f[i-1][j+2^(i-1)]。
②不過區間在增加時,每次並不是增加乙個長度,而是基於倍增思想,用二進位制右移,每次增加2^i個長度 ,最多增加logn次
這樣預處理了所有2的冪次的小區間的最值
關於倍增法鏈結
查詢:
③對於每個區間,分成兩段長度為的區間,再取個最值(這裡的兩個區間是可以有交集的,因為重複區間並不影響最值)
比如3,4,6,5,3一種分成3,4,6和6,5,3,另一種分成3,4,6和5,3,最大值都是6,沒影響。
首先明確 2^log(a)>a/2
這個很簡單,因為log(a)表示小於等於a的2的最大幾次方。比如說log(4)=2,log(5)=2,log(6)=2,log(7)=2,log(8)=3,log(9)=3…….
那麼我們要查詢x到y的最小值。設len=y-x+1,t=log(len),根據上面的定理:2^t>len/2,從位置上來說,x+2^t越過了x到y的中間!
因為位置過了一半,所以x到y的最小值可以表示為min(從x往後2^t的最小值,從y往前2^t的最小值),前面的狀態表示為f[t][x]
設後面(從y往前2^t的最小值)的初始位置是k,那麼k+2^t-1=y,所以k=y-2^t+1,所以後面的狀態表示為f[t][y-2^t+1]
所以x到y的最小值表示為f(f[t][x],f[t][y-2^t+1]),所以查詢時間複雜度是o(1)
④所以o(nlogn)預處理,o(1)查詢最值 但不支援修改
預處理時間複雜度o(nlogn),查詢時間o(1)。
#include#include#include#includeusing namespace std;
int map[1000005][20];
int n,k;
void work()
int question(int z,int y)
int main()
return 0;
}
瘋子的演算法總結14 ST演算法(區間最值)
借助倍增和動態規劃可以實現o 1 的時間複雜度的查詢 預處理 區間dp 轉移方程 f i j min max同理 f i j 1 f i j 1 f i j 表示從i位置開始的後2 j個數中的最大值 用f i j 表示從j到j 2 i 1的最小值 長度顯然為2 i 任意一段的最小值顯然等於min 前...
st演算法模板(區間最值)
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 j 1 平均分成兩段 因為j 1時,f i,...
求解區間最值的ST演算法
作用 st演算法是用來求解給定區間rmq的最值,本文以最小值為例 舉例 給出一陣列a 0 5 則區間 2,5 之間的最值為1。1 離線預處理 運用dp思想,用於求解區間最值,並儲存到乙個二維陣列中。具體解釋 1 離線預處理 st演算法使用dp思想求解區間最值,貌似屬於區間動態規劃,不過區間在增加時,...