运用倍增思想实现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 }

 

posted @ 2022-08-08 21:19  次林梦叶  阅读(46)  评论(0)    收藏  举报