简介
st 表也可以翻译为稀疏表。
被用于解决 RMQ,gcd 问题(区间最值),O(nlogn) 预处理,O(1) 查询。
问题要满足可重复贡献。例如 max(aL→R) 。
即可以表示为 max(aL→k,ak+1→R),也可表示为 max(aL→R−1,al+1→R)。即使可能有重复的部分,也没有影响。
推导与使用
基于这种思路,我们就可以通过倍增,动态规划的思想实现。以下为区间最大值的推导。定义 fi,j 为从 i 开始,长度为 2j 的最大值。
状态方程就是:
fi,j=max(fi,j−1,fi+2j−1,j−1)
ai 即为 fi,0 的最大值(区间长度为 1)。
代码
for(int j=1;j<=LogN;j++) {
for(int i=1;i+(1<<j)-1<=n;i++) {
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
}
查询
根据前文,我们可在 O(1) 的时间复杂度内查询从 i 开始,长度为 2j 的区间。查询操作就是把大区间变成两个可能有重复的,小的,长度为 2j 的区间。
例如 125 ,可以被分解为 [1,64],[62,125] 两个区间。
以下是查询区间 [l,r] 长度为 N 的区间。
区间长度
在两个区间内包含,所以长度为 2log2N。(指数向下取整)
小细节
如果每次求 log2N 会很慢。预处理可以变成 O(1)。
logi=log2i+1。特别地,log1=0。
区间开头
一些练习(可能按照难度排序)
- JSOI2008-最大数
改变一般 st 表的结构,从以 i 开头,变成以 i 结尾,使 st 表可更新元素。
同时有个小技巧,st 表也可以存储下标,达到与存最大值相同效果。
- 章节划分
一道比较难的蓝题,结合了分治,递归,挺难想的。
- CERC2013-Magical GCD
结合二分,其实也不算难。
- NOI2010-超级钢琴
思维难度挺大的,不是很会想,锻炼一下思维吧,特别是结合了优先队列优化时间,贪心的思想很重要,也是我自己弄懂的第一道紫,挺有纪念意义的。自己的题解