# sparse table稀疏表 * 建立一個二維陣列,sp[N][$\lfloor log_2N\rfloor$],N為數字長度,$\lfloor log_2N\rfloor$為2最接近N的整數對數 * sp[i][j]為位置i到i+$2^j$的最小值 {0<=j<=$\lfloor log_2N\rfloor$} * **建立**:(最小值為例) 1. sp[i][j]=min(sp[i][j-1], sp[i+$2^{j-1}$][j-1]) -- ex:i到$2^3$為min( i到i+4的min, i+4到(i+4)+4的min ) 2. 複雜度$O(n\log n)$ * **取值**: 1. 取[l, r], **LEN=l-r+1**, **j=$\lfloor log_2LEN\rfloor$** 2. 輸出即為 min(sp[l][j], sp[r-$2^j$+1][j]) 3. 其原理為,即便取到重複的範圍,如[2,2+4]和[7-4, 7],也不會影響極值的數值,因此可達到O(1)的速度 :::info 不能做修改,因為一個值會被很多範圍覆蓋 ::: > $2^j$ c++ code: ```1<<j``` > log則預先生成 程式碼: ```cpp= #include <bits/stdc++.h> using namespace std; int num[500001], sp[500001][20], log_2[500001]; int query(int l, int r){ int k=log_2[r-l+1]; return min(sp[l][k], sp[r-(1<<k)+1][k]); } int main(){ ios_base::sync_with_stdio(false); cin.tie(0); int n cin >> n; // generates logarithm table of 2 (only needs n value) log_2[1]=0; for(int i=2;i<=n;++i) log_2[i]=log_2[i/2]+1; //build for(int i=0;i<n;++i){ //init cin >> num[i]; sp[i][0]=num[i]; } for(int j=1;j<=log_2[n];++j) for(int i=0;i+(1<<j)-1<n;++i) sp[i][j]=max(sp[i][j-1], sp[i+(1<<(j-1))][j-1]); } ```