关于
RMQ ,即 Range Maxnum (Minnum) Query 。用于查询静态区间最大(最小)值,
思路基于动态规划 (DP)
思路
设 F[i][j] 为 [i,i+2j] 区间内的的最大值,那么 F[i][0] 就是我们输入的数。
不难想到一个区间可以被分成两边
![](https://i-blog.csdnimg.cn/blog_migrate/6abb972026d9734661f9399e6eecfb4f.png)
当前区间的最大值就是左右两区间的最大值,即 \(F[i][j]=\max(F[i][j-1],F[i+2^{j-1}][j-1])\)
查询
对于区间 \([l,r]\) 先求 \(k=\lfloor \log^2_{r-l+1}\rfloor\)
答案即为 \(\max(F_{l,k},F_{r-2^k+1,k})\) 可以忽略中间重叠的部分,不影响结果
实现
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n,T,l,r,k,f[100005][35],p[35]={1};
int main(){
for(register int i=1;i<31;i++) p[i]=p[i-1]<<1;
scanf("%d%d",&n,&T);
for(register int i=1;i<=n;i++) scanf("%d",&f[i][0]);
for(register int j=1;j<31;j++)
for(register int i=1;i+p[j-1]-1<=n;i++)
f[i][j]=max(f[i][j-1],f[i+p[j-1]][j-1]);
while(T--){
scanf("%d%d",&l,&r);
k=log2(r-l+1);
printf("%d\n",max(f[l][k],f[r-p[k]+1][k]));
}
}
时间复杂度:\(O(n)\)预处理,\(O(1)\)查询,可用于大量查询的静态区间
动态的话还是要考虑线段树等数据结构