ST表标程

P3865 ST表板子题

ST表是通过倍增算法快速处理RMQ问题的一个算法

#include <bits/stdc++.h>
using namespace std;
const int logn=21;
const int maxn=2000001;
int f[maxn][logn+1],Logn[maxn+1];//f是[i,2^j-1]的最大值,Logn看函数 

inline int FRead(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f;}

void pre(){//提前算好log2(n) 
	Logn[1]=0;
	Logn[2]=1;
	for(int i=3;i<maxn;i++){
		Logn[i]=Logn[i/2]+1;
	}
}

int main(){
	int n=FRead(),m=FRead();
	for(int i=1;i<=n;i++) 
		f[i][0]=FRead();
	pre();
	for(int j=1;j<=logn;j++)//j在外面,因为递推需要 
		for(int i=1;i+(1<<j)-1<=n;i++)//注意i的范围,不然对应j会超出n 
	   		f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); //实现ST表 
	for(int i=1;i<= m;i++) {
		int x=FRead(),y=FRead();//每次询问 
		int l=Logn[y-x+1];//长度 
		printf("%d\n",max(f[x][l],f[y-(1<<l)+1][l]));//通过分成两个区间,取得区间内最大值 
	}
	return 0;
}








区间gcd和RMQ是本质上一样的问题,
只需要把主函数作出如下修改:

int main(){
	int n=FRead(),m=FRead();
	for(int i=1;i<=n;i++) 
		f[i][0]=FRead();
	pre();
	for(int j=1;j<=logn;j++)//j在外面,因为递推需要 
		for(int i=1;i+(1<<j)-1<=n;i++)//注意i的范围,不然对应j会超出n 
	   		f[i][j]=__gcd(f[i][j-1],f[i+(1<<(j-1))][j-1]); //实现ST表 
	for(int i=1;i<= m;i++) {
		int x=FRead(),y=FRead();//每次询问 
		int l=Logn[y-x+1];//长度 
		printf("%d\n",__gcd(f[x][l],f[y-(1<<l)+1][l]));//通过分成两个区间,取得区间内最大值 
	}
	return 0;
}
posted @ 2023-08-23 09:43  CultReborn  阅读(9)  评论(0)    收藏  举报