【模板】st表

利用了倍增的思想,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[1 << i] = i;
for(int i = 1; i <= n; i++)
    if(!Log2[i]) Log2[i] = Log2[i - 1];
处理log2

查询[l, r]区间的最值:

扫描二维码关注公众号,回复: 443565 查看本文章

取区间[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 const int 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);
18     for(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 }

猜你喜欢

转载自www.cnblogs.com/devilk-sjj/p/9021574.html
今日推荐