RMQ(Range Minimum/Maximum Query)

$RMQ$又叫$st$表,本质上是一种倍增动态规划,用来求解区间最大值。

通过预处理,快速查询区间最大值。

定义$f[i][j]$表示从$i$开始,区间长度是$2^j$的区间中的最大值是多少。

和$tarjan$的想法一样,以区间的中间点为分界点,可以容易得到递推式$f[i][j] = max(f[i][j - 1] + f[i + 2^{j-1}][j - 1])$。

状态数量第一维是$n$,第二维是$logn$,所以该算法的时间复杂度是$O(nlogn)$的。

acwing 1273.天才的记忆

https://www.acwing.com/problem/content/description/1275/

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 
 6 using namespace std;
 7 
 8 const int N = 2e5+10, M = 18;
 9 
10 int a[N];
11 int f[N][M];
12 int n, m;
13 
14 void init()
15 {
16     for(int j = 0 ; j < M ; j ++)
17         for(int i = 1 ; i + (1 << j) - 1 <= n ; i ++)
18             if(!j)f[i][j] = a[i];
19             else f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
20 }
21 
22 int query(int l, int r)
23 {
24     int len = r - l + 1;
25     int k = log(len) / log(2);
26     
27     return max(f[l][k], f[r - (1 << k) + 1][k]);
28 }
29 
30 int main(){
31     cin >> n;
32     for(int i = 1 ; i <= n ; i ++)cin >> a[i];
33     cin >> m;
34     init();
35     
36     while(m --)
37     {
38         int l, r;
39         cin >> l >> r;
40         cout << query(l, r) << endl;
41     }
42     return 0;
43 }

猜你喜欢

转载自www.cnblogs.com/1-0001/p/12606298.html