【C++】ST表求RMQ问题--代码+分析

洛谷 P3865 【模板】ST 表 & RMQ 问题

题目描述

给定一个长度为 N 的数列,和 M 次询问,求出每一次询问的区间内数字的最大值。

输入格式

第一行包含两个整数 N,M,分别表示数列的长度和询问的个数。

第二行包含 N 个整数(记为 ai​),依次表示数列的第 i 项。

接下来 M 行,每行包含两个整数 li​,ri​,表示查询的区间为 li​,ri​

输出格式

输出包含 M 行,每行一个整数,依次表示每一次询问的结果。

输入输出样例

输入 #1

cpp 复制代码
8 8
9 3 1 7 5 6 0 8
1 6
1 5
2 7
2 6
1 8
4 8
3 7
1 8

输出 #1

cpp 复制代码
9
9
7
7
9
8
7
9

做法&代码

定义 fij : 从 i 开始,2^j 步内,区间最大值 。

AC记录1AC记录2。这里展示两种代码,仅细节差别。日后会详解 ST表。

解释在注释里。

简洁版

此代码于另一段的区别:直接调用 <cmath> 库中的 log 函数。

cpp 复制代码
#include<iostream>
#include<cmath>
using namespace std;

int n,m,f[100010][20];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>f[i][0];
	
	int lg=log2(n);//log 
	for(int j=1;j<=lg;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]);
	}//预处理 
	
	for(int i=1;i<=m;i++) {
		int x,y,l;
		cin>>x>>y;
		l==log2(y-x+1);
		cout<<max(f[x][l],f[y-(1<<l)+1][l])<<'\n';//查询 
	}
	return 0;
}//ST elseif123 on 2026/2/5

推荐版

自己手写 log,并把功能封装到函数。

cpp 复制代码
#include<iostream>
using namespace std;
const int N=1e5+7;

int n,m;
int f[N][20],lg[N];

void init() {//预处理 
	for(int j=1;(1<<j)<=n;j++)
		for(int i=1;i+(1<<j)/*相当于 2^j*/-1<=n;i++)
			f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
	
	lg[1]=0;
	for(int i=2;i<=n;i++)
		lg[i]=lg[i/2]+1;
}

int query(int l,int r) {//查询 
	int k=lg[r-l+1];
	return max(f[l][k],f[r-(1<<k)+1][k]);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>f[i][0];
	init();
	
	for(int i=0;i<m;i++) {
		int x,y;
		cin>>x>>y;
		cout<<query(x,y)<<'\n';
	}
	return 0;
}
相关推荐
ysu_03141 天前
05 | 持久化撤销提示非核心功能
算法·游戏程序
浮沉9871 天前
二分查找算法概述&通用模板
算法
Keven_111 天前
算法札记:SPFA判负环算法的证明
算法
什巳1 天前
JAVA练习278- 和为 K 的子数组
java·学习·算法·leetcode
Jerry1 天前
LeetCode 347. 前 K 个高频元素
算法
Young Doro1 天前
SAC 算法
线性代数·算法·机器学习
罗超驿1 天前
2.算法效率的核心密码:时间复杂度和空间复杂度详解
java·数据结构·算法
:-)1 天前
算法-堆排序
数据结构·算法·排序算法