运用倍增思想实现RMQ(RMQ (Range Minimum/Maximum Query))问题
本博客大部分是我对这位大佬的文章的个人理解:https://blog.csdn.net/weixin_45697774/article/details/105289810
《倍增》


《RMQ问题》

对于这道题:
(这个f数组被称为ST表)
1.首先定义一个数组 f[N][logN+1],这个数组f[i][j]表示在点i出往后2^j个长度内,即[i,i+2^j]的区间中的最大值为f[i][j];

2.对于给出的区间询问[l,r],如何求出其中最大值呢?
k又是如何取的呢?
k=log(r-l+1)/log(2);
l+2^k-1<=r, l+2^(k+1)-1>r
r-2^k+1>=l, r-2^(k+1)-1<l
3.如何求f[i][j]?

可知:正如dp一样,可以推出来
1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 #include <cmath>
5 using namespace std;
6 const int N = 200010;
7 // 17<logN 18>logN;
8 int a[N], f[N][18];
9 int main()
10 {
11 int n;
12 cin >> n;
13 for (int i = 1; i <= n; i++)
14 scanf("%d", &a[i]);
15
16 //开始处理f数组,f[i][j]:表示在点i处往后2^j的长度范围内的区间最大值
17 //即[l,l+2^j]的最大值
//时间复杂度O(nlogn)
18 for (int i = n; i >= 1; i--)
19 {
20 f[i][0] = a[i];
21 for (int j = 1; i + (1 << j) - 1 <= n; j++)
22 f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
23 }
24 int m;
25 cin >> m;
26 while (m--)
27 {
28 int l, r;
29 scanf("%d%d", &l, &r);
30 //开始通过ST表(f数组)查找答案:
31 int len = r - l + 1;
32 int k = log(len) / log(2);
33 int ans = max(f[l][k], f[r - (1 << k) + 1][k]);
34 cout << ans << endl;
35 }
36 return 0;
37 }

浙公网安备 33010602011771号