RMQ问题中的ST算法
RMQ问题中的ST算法
RMQ(Range Minimum Query,区间最小值查询)问题是计算机科学中一个经典的问题,它在很多实际应用中都有广泛的应用,如图像处理、信号处理等。稀疏表算法是解决RMQ问题的一种高效方法。本文将详细介绍稀疏表算法的原理及算法流程,并给出相关的C++代码实现。
原理
稀疏表算法的基本思想是将原始数据集构建成一个稀疏矩阵,然后通过查询稀疏矩阵来得到区间最小值。稀疏矩阵中的非零元素表示原始数据集中的最小值,而零元素则表示原始数据集中没有最小值的位置。通过这种方式,我们可以在O(1)的时间复杂度内完成区间最小值的查询。
算法流程
稀疏表算法的流程如下:
-
初始化:创建一个大小为n×m的二维数组S,其中n表示原始数据集的大小,m表示查询区间的大小。将S的所有元素初始化为0。
-
构建稀疏矩阵:遍历原始数据集,对于每个数据点d[i],如果其在查询区间[l, r]内,则更新S[i][j] = min(S[i][j], d[i]),其中j表示当前查询区间的下标。
-
查询区间最小值:给定一个查询区间[l, r],遍历稀疏矩阵S,找到第一个大于等于0的元素S[i][j],此时S[i][j]即为区间[l, r]的最小值。
C++代码实现
下面给出稀疏表算法的C++代码实现:
// RMQ问题中的ST算法
// m次询问,求l~r中最大值是多少
#include<bits/stdc++.h>
#define reg register
using namespace std;
// 读取输入的函数
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
// 输出结果的函数
inline void write(int x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
return ;
}
const int MAXN=100005;
vector<int > a; // 存储输入数据的数组
int n,f[MAXN][21],m; // f[i][j]表示区间[i, j]的最大值
// ST预处理函数
void ST_prework(){
for(reg int i=1;i<=n;i++) f[i][0]=a[i]; // 将第一个元素作为区间的最大值
int t=log(n)/log(2)+1; // 确定二维数组f的维度
for(reg int j=1;j<t;j++){ // 从第二个维度开始遍历二维数组f
for(reg int i=1;i<=n-(1<<j)+1;i++){ // 从第一个维度开始遍历一维数组f的第一部分
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); // 根据状态转移方程更新f[i][j]的值
}
}
return ;
}
// ST查询函数,返回区间[l, r]的最大值
int ST_query(int l, int r){
int g=log(r-l+1)/log(2); // 计算区间长度的对数,向上取整得到二进制位数g
return max(f[l][g],f[r-(1<<g)+1][g]); // 根据状态转移方程和边界条件返回区间最大值
}
// 主函数,读取输入数据,调用ST预处理函数和查询函数,输出结果
int main(){
n=read(),m=read(); // 读取输入数据的数量n和查询次数m
a.push_back(0); // 在a数组末尾添加一个元素,用于记录空元素的位置,方便后续处理边界情况
for(reg int i=1;i<=n;i++)a.push_back(read()); // 按照顺序读取输入数据并存储到a数组中
ST_prework(); // 对输入数据进行预处理,构建ST表f
for(reg int i=1;i<=m;i++){ // 对于每次查询,调用ST查询函数并输出结果
int p=read(),q=read(); // 读取查询的起始位置p和结束位置q
write(ST_query(p, q)); // 将查询结果写入输出流中,并换行分隔每个查询结果
putchar('\n'); // 在每次查询后换行,使得输出更加清晰易读
}
return 0;
}
例题及题解
例题:给定以下数据集和查询区间:
5 4
1000000000 999999998 999999997 999999996 999999995
1000000001 1000000002 1000000003 1000000004 1000000005
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)