【学习笔记】倍增ST表、LCA学习笔记
众所周知,scy5赛时在P10059 Choose写了个滑动窗口骗 口吐芬芳的图:
听说这题可以用ST表做,但他不会,于是他就来学倍增乐。
省流:被吊打了
更改日志
2024/01/16:开坑。
倍增原理
设做一件事有
模拟想法:我们可以一个一个步骤去做,时间复杂度
有满足条件为:用第
那么我们可以预处理出
如
时间复杂度
理解倍增
我们拿快速幂来当作例子(应该都会)。
大意
求
数据太大,模拟的时间复杂度为
其实快速幂也可以用倍增优化。
可以发现,求幂次就满足倍增的条件:用第
因为
然后就可以先求出
最后求
那么,如
二进制拆分应该都会,就不写了(懒)
二进制拆分就是算出
ST表(RMQ)
P3865 【模板】ST 表
题目描述
给定一个长度为
输入格式
第一行包含两个整数
第二行包含
接下来
输出格式
输出包含
提示
对于
对于
对于
解法
这题先考虑暴力,每次找一遍区间最大值,时间复杂度
那么我们去想:这题是否满足倍增的条件:用第
答案是肯定的,因为我们可以知道,如果我们知道了两个相邻区间的最大值,那么这个大区间的最大值就是两者取
那么定义一个数组
首先,所有的
然后,当
这样预处理的时间复杂度为
那么,预处理就好了。
然后是调用。
那么我们就对区间长度(就是
然后二进制拆分即可。
CODE:
#include<bits/stdc++.h>
using namespace std;
int n,m,l,r,a[100010],ST[100010][20];
int qpow(int a,int b){//快速幂
int ret=1;
while(b){
if(b%2!=0){
ret=ret*a;
}
a=a*a,b/=2;
}return ret;
}int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
ST[i][0]=a[i];//初始化
}for(int j=1;j<=20;j++){//枚举幂次
for(int i=1;i+qpow(2,j)-1<=n;i++){//枚举起点
ST[i][j]=max(ST[i][j-1],ST[i+qpow(2,j-1)][j-1]);//转移
}
}for(int i=1;i<=m;i++){
scanf("%d%d",&l,&r);
int len=r-l+1,ret=-1,cnt=0;
for(int j=0;j<20;j++){
if(len%2==1){//若这一位为一
ret=max(ret,ST[l+cnt][j]);//那么就尝试更新
cnt+=qpow(2,j);//下一个拆出的区间
}len/=2;//去掉这一位
}printf("%d\n",ret);
}return 0;
}
咕咕咕
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构