专栏文章
ST 表 SPARSE TABLE
科技·工程参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqy7s8i
- 此快照首次捕获于
- 2025/12/04 12:41 3 个月前
- 此快照最后确认于
- 2025/12/04 12:41 3 个月前
前言
ST 表是一种基于预处理、倍增、分块的数据结构,主要解决 RMQ 问题,并且就离线询问来讲(它也只能离线询问)是相当高效的,当然预处理的可能要稍微花点与其他数据结构同级别的时间,不太支持修改,与最值强联系的性质才能用。
正文
0x01.ST 表基础
理论基础
有一种东西,叫做二的次幂,还有一种东西,叫做对数,对于很大的数量,比如说 ,取一个以 为底的对数(取整)就可以得到极小的 ,降了 个数量级。
还有最值,有一种性质是
也就是对于一段整数序列的区间 内,有 满足 。
那么对于一段长度为 序列 ,我们可以对于每个位置记录 个 表示区间 内的 或者 ,于是对于任意的离线询问 的最值,答案就是
具体的,就可以在 的时间复杂度内预处理,然后 离线查询区间最值哩。
代码实现
假设给定一个序列,离线求区间最大值。
首先,为了避免 带来的较大常数,我们一般预处理出 ,时间复杂度 。
然后为了得到 ,因为 ,所以按照区间以二的次幂增大的方式更新每个位置的 ,有一个 的对 的预处理,然后时间复杂度 。
最后,在询问时,先处理出区间长度对应的 整数,然后借助理论基础里的式子就可以 得到想要的答案。
然后为了得到 ,因为 ,所以按照区间以二的次幂增大的方式更新每个位置的 ,有一个 的对 的预处理,然后时间复杂度 。
最后,在询问时,先处理出区间长度对应的 整数,然后借助理论基础里的式子就可以 得到想要的答案。
以下是样例代码:
CPP#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int n,m;
int a[N];
int st[N][12];
int logn[N];
void init(){
logn[1]=0;
for(int i=2;i<=n;i++) logn[i]=logn[i/2]+1;//取对数
for(int j=1;j<=logn[n];j++)//枚举区间长度
for(int i=1;i+(1<<j)-1<=n;i++)//枚举位置,更新st数组
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
int ask(int l,int r){//O(1)查询
if(l>r) return 0;
int t=logn[r-l+1];
return max(st[l][t],st[r-(1<<t)+1][t]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),st[i][0]=a[i];//输入+预处理
init();
for(int i=1,l,r;i<=m;i++){
scanf("%d%d",&l,&r);
printf("%d\n",ask(l,r));
}
return 0;
}
贝斯特的优化:有一种东西,叫做地址访问优化,也就是对于数组来讲,维数小的放前面,会比维数大的放前面访问更快,这种东西对于极大的数组来讲,优化相当之大,在状态压缩等应用中也有十足的表现。
贝蒂的练习
- P3865 【模板】ST 表 && RMQ 问题
- P4392 [BOI2007] Sound 静音问题 当然可以单调队列做,但是 ST 表也不是不行,毕竟 ST 表打熟了,比单调队列好调。
- P2471 [SCOI2007] 降雨量 小小分类讨论,不足为惧。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...