RMQ详解

浪子不回头ぞ 提交于 2019-12-10 02:44:40

RMQ问题

:查询区间最大值或者最小值

这里用ST表处理

ST表(动态规划的思想)

f [i][st], i为元素起始下标,st为从i开始,长度为2^st 的最大值

1.预处理

  f[i][0] 为从i 开始,长度为2^0 范围的最大值

for(int i=1;i<=n;i++){
		f[i][0]=a[i];
	}

2.  f[i][0]    [i,i]

     f[i][1]    [i,i+1]  = max( f[i][0], f[i+2^0][0] )

     f[i][2]    [i,i+3]  = max( f[i][1],f[i+2^1][1] )

     f[i][3]    [i,i+7]   = max( [i,i+3], [i+4,i+7] ) = max( f[i][2],f[i+2^2][2] ) 

    可以看出,对于区间为[i,st] 的区间,可以拆为 f[i][st-1]  和 f[i+2^(st-1)][st-1])

其实就是将区间对半,然后将两个半区间再比较最大值

循环下界问题

1.  这里的 j 的上限为 2^j<=n,  (1<<j 表示2^j)

  关于1<<j 的解释

   1 左移 j 位
    这是移位运算,左移
  1<<1 表示把 
二进制 数 0001 左移 1 位,变成 0010, 等于 2
  1<<4 表示把 
二进制 数 0001 左移 4 位,变成 0001 0000, 等于 16

2.  i 的坐标也不能越界,i+2^j <= n+1具体解释看大佬博客

for(j=1;(1<<j)<=n;++j)
	  for(i=1;i+(1<<(j-1))<=n;++i)
	    f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);

至于查询,设k=log(r- l +1),则 因为k为下取整结果,最后可能长度不能覆盖(r-l+1),例如区间为[1,12]

而k最大=3 ,长度为8,到不了12,

所以用max( f[l][k] ,f[r-(1<<k)+1][k] ) ,即max( [1,8] , [5,12] )

以m为底的log函数表达式为 log(n)/log(2)或者直接写成 log2(n)

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int f[maxn][25];
int main(){
	 int n,m;
	 scanf("%d %d",&n,&m);
	 for(int i=1;i<=n;i++){
	    scanf("%d",&a[i]);
	 	f[i][0]=a[i];
	 }
	 for(int j=1;(1<<j)<=n;j++){
	 	for(int i=1;i<=(n-(1<<j)+1);i++){
	 		f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		 }
	 }
	 int l,r,k;
	 for(int i=1;i<=m;i++){
	 	scanf("%d %d",&l,&r);
	 	k=log(r-l+1)/log(2);
	 	int b=max(f[l][k],f[r-(1<<k)+1][k]);
	 	printf("%d\n",b); 
	 }
	 return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!