RMQ问题(ST算法)

一、RMQ算法:

询问某个区间的最大值或最小值,适用于没有修改操作并且查询次数较多的情况;

二、ST算法的流程

1、预处理:

整个区间的最大值一定是左右两边的最大值的最大值,以i为起点,2^j+i为终点,如此可以写出状态转移方程;

f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1]),并且时间复杂度是O(n*log(n));

2、询问:

询问区间[li,ri]的最大值先求出最大的x满足2^x<=ri-li+1;

[li,ri]=[li,li+2^x-1]U[ri-2^x+1,ri](对称记忆);

问题描述:

输入n个数字,查询m次,每次输入x,y两个数,表示查询的范围,求出x到y区间的最大数;

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn1 = 1e6+5;
const int maxn2 = 25;
int a[maxn1],f[maxn1][maxn2],log[maxn1];
int n,m,x,y;
int main(void)
{
	int i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++) scanf("%d",&a[i]);
	log[0]=-1;
	//预处理 
	for(i=1;i<=n;i++) 
	f[i][0]=a[i],log[i]=log[i>>1]+1; 
	//计算f[i][j]; 
	for(j=1;j<=maxn2;j++)
	{
		for(i=1;i+(1<<j)-1<=n;i++)
		f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
	}
	//查询 
	scanf("%d",&m);
	while(m--)
	{
		scanf("%d %d",&x,&y);
		int s=log[y-x+1];
		printf("%d\n",max(f[x][s],f[y-(1<<s)+1][s]));
	}
	return 0;
} 


/*
10
3 2 4 5 6 8 1 2 9 7
2
1 4
3 8
*/

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/82893973
今日推荐