ST表学习笔记(未完)
2025-06-07 11:36:29
发布于:上海
观前说明:作者菜 无条件接受所有正常建议 轻喷
写作目的:发现ACGO好像没有较为详细地有关ST表的文章 最近刚好在学 觉得写这个帮助清晰思路 就写了
注释:本文有参考xiaoshumiao(洛谷)的ST表,天泽龟(洛谷)的P3865 【模板】ST 表 && RMQ 问题 题解 和 进阶算法思想(洛谷课程)
前置:
1.小学语文,数学知识(不提供讲解):
如:=
2.二进制分解思想:
以2020 CSP-J T1:优秀的拆分为例:
=
的二进制:1000
的二进制:10010
正文开始:
1.应用:用于快速求出区间内最小/最大值的数据结构
2.思想:利用倍增思想(来缩短时间)
倍增思想:
倍增是基于二进制分解思想的预处理算法.
*二进制分解思想:具体参考2020 CSP-J T1:优秀的拆分
倍增主要用于优化树结构中的跳跃路径查询问题
操作方式:记录每个节点向上跳跃层的祖先节点
而在ST表中,倍增思想的体现在于其数组的定义
似乎比较难懂.可以再看这题倍增快速幂
这道题主要是求:
b使用二进制拆分:b=
*这里的每一个都已二次方形式表现 也就是
由此,最后需要求的变成:
设为 也可以转变为 也就是 (回收开头之小学数学知识)
那么,需要转换的变成:
*这里的等没有特定的数值.它们的数值取决于是多少:
=
似乎更难懂了
代入几个数值:
a=3 , b=5
b=
=
=
此次代入数值的成果:
1.理清思路
2.明白需要初始化:不可能从来
3.明白并不是连续的,但是从到的每一个都需要求出,尽管它们中有一部分不需要(但为了求它们的后续值,依然需要将它们求出)
丑陋代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
long long a,b,q;
cin>>a>>b>>q;
int na=a;
int nb=b;
long long answer=1;
int shu=0;
long long sum=0;
while(1){
if(b==0)break;
if(shu==0){
sum=a;
}else sum=sum*sum%q;
if(b%2==1){
answer*=sum;
answer%=q;
}
shu++;
b/=2;
}
cout<<na<<"^"<<nb<<" "<<"mod"<<" "<<q<<"="<<answer;
return 0;
}
然后,可以观察一下本题的时间复杂度:如果说,直接乘b次a的话,时间复杂度是 但是(似乎是)使用了倍增后,它的时间复杂度降到了
3.实现:(此处从P3865 【模板】ST 表 && RMQ 问题入手)
这道题分为两个阶段:预处理阶段&求最值阶段
一.预处理阶段
这里的"预处理"指的是使用一个二维数组f,存储所有区间的最值.
表示以p为左端点,长度为的区间的最大值.(回收上文倍增思想的体现)
考虑=这个式子(回收开头).长度为的区间可拆成两个长度为次方的小区间.
第一个区间的端点为p,第二个区间的端点为.
递推式:
这里空空如也
有帮助,赞一个