ST 表 SPARSE TABLE
前言
第一服役期都要结束了还写什么博客
ST 表是一种基于预处理、倍增、分块的数据结构,主要解决 RMQ 问题,并且就离线询问来讲(它也只能离线询问)是相当高效的,当然预处理的可能要稍微花点与其他数据结构同级别的时间,不太支持修改,与最值强联系的性质才能用。
正文
0x01.ST 表基础
理论基础
有一种东西,叫做二的次幂,还有一种东西,叫做对数,对于很大的数量,比如说
还有最值,有一种性质是
也就是对于一段整数序列的区间
那么对于一段长度为
具体的,就可以在
代码实现
假设给定一个序列,离线求区间最大值。
首先,为了避免
然后为了得到
最后,在询问时,先处理出区间长度对应的
以下是样例代码:
#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] 降雨量 小小分类讨论,不足为惧。