【模板】st表
阿新 • • 發佈:2018-05-10
st表 序列 spl line col ++ hide 處理 表示
利用了倍增的思想,st[i][j]表示[i, i + 2j - 1]的區間內的最(大、小)值
自然st[i][0]存的就是序列中的第i個數,區間[l, r]的長度為log2(r - l + 1)
預處理:
處理每個為2的倍數的區間:
區間 [i, i + 2j] 的值為區間 [i, i + 2j - 1] 和區間 [i + 2j - 1, i + 2j] 的最值
復雜度O(n log2 n)
關於每次取log2,用cmath裏的函數會很慢(保留了小數)
所以可以預處理出log2(i)的整數值
for(int i = 0; (1 << i) <= n; i++) Log2[處理log21 << i] = i; for(int i = 1; i <= n; i++) if(!Log2[i]) Log2[i] = Log2[i - 1];
查詢[l, r]區間的最值:
取區間[l, l + 2k - 1]和區間[r - 2k + 1, r]的最值
復雜度O(1)
其實蠻好理解的...QwQ
【代碼:】
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 using namespace std; 5 6 constint MAXN = 1e5 + 1, MAXM = 1e6 + 1; 7 const int K = 18; 8 9 int n, m; 10 int a[MAXN], st[MAXN][K], Log2[MAXN]; 11 12 int Query(int l, int r) { 13 int x = Log2[r - l + 1]; 14 return max(st[l][x], st[r - (1 << x) + 1][x]); 15 } 16 int main() { 17 scanf("%d%d", &n, &m); 18for(int i = 1; i <= n; i++) scanf("%d", &a[i]); 19 for(int i = 1; i <= n; i++) st[i][0] = a[i]; 20 for(int j = 1; j <= K; j++) { 21 for(int i = 1; i + (1 << j) - 1 <= n; i++) 22 st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); 23 } 24 for(int i = 0; (1 << i) <= n; i++) 25 Log2[1 << i] = i; 26 for(int i = 1; i <= n; i++) 27 if(!Log2[i]) Log2[i] = Log2[i - 1]; 28 while(m--) { 29 int l, r; 30 scanf("%d%d", &l, &r); 31 printf("%d\n", Query(l, r)); 32 } 33 }
【模板】st表