c++ RMQ

关于

RMQ ,即 Range Maxnum (Minnum) Query 。用于查询静态区间最大(最小)值,
思路基于动态规划 (DP)

思路

设 F[i][j] 为 [i,i+2j] 区间内的的最大值,那么 F[i][0] 就是我们输入的数。
不难想到一个区间可以被分成两边

当前区间的最大值就是左右两区间的最大值,即
\(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)\)查询,可用于大量查询的静态区间
动态的话还是要考虑线段树等数据结构

posted @ 2021-01-26 10:41  小蒟蒻laf  阅读(157)  评论(0编辑  收藏  举报