当前位置: 首页 > news >正文

算法知识-倍增算法

一.RMQ

1.RMQ

RMQ,即区间查询,是指这样一个问题:对于长度为n的数列A,回答若干次询问RMQ(A,i,j),返回数列中下标在i,j之间的最小/大值。

2.符号约定

假设一个算法预处理时间为f(n),查询时间为g(n),这个算法的复杂度记为<f(n),g(n)>

RMQA(i,j)来表示数组A中索引i和j之间最小值的位置

3.RMQ相关算法

(1)在线暴力遍历算法:

假设数据的规模:N,查询数:Q

单次查询时间复杂度:O(N)

总的时间复杂度:O(N*Q)

(2)预处理+直接查询

预处理:枚举所有区间,然后每个区间遍历查找,之后f[i][j]表示区间[i,j]之间的最小值

复杂度:<O(N^3),O(1)>

(3)预处理的DP优化

复杂度:<O(N^2),O(1)>,而且空间复杂度也是O(N^2)

优缺点:查询效率高,预处理效率太低

(4)线段树

复杂度:<O(n),O(logn)>

(5)分块算法

(6)ST表算法

二.ST表

ST表中M数组的含义

M[i][j],表示从下标i开始,长度为2^j的子数组的最小值的索引

ST表算法的DP预处理

把 M [i][j] 对应的区间平均分成两段(M [i][j] 对应的区间长度一定为偶数),从 i 到为前一段,为后一段 (长度都为),则 M [i][j] 就是这两段的最小值中的最小值对应的索引。

可得 DP 状态转移方程:

if(a[M[i][j-1]] < a[M[i+2^{j-1}][j-1]]) M[i][j] = M[i][j-1]

else M[i][j] = M[i+2^{j-1}][j-1]

其中,初始化:M [i][0] = i

ST表算法的查询实现

预处理M[i][j]完成以后,如何进行RMQA(i,j)查询?

查询实现:选择两个能够完全覆盖区间[i..j]的块,并且

找到它们之间的最小值。设k = [log₂(j-i+1)](向下取整),则得:

if(a[M[i][k]] < a[M[j-2ᵏ+1][k]]) RMQA(i,j) = M[i][k],

else RMQA(i,j) = M[j-2ᵏ+1][k]

M[i][k]——从查询区间起始点i开始,向后长度为2ᵏ的一段

M[j-2ᵏ+1][k]——从查询区间尾j开始,向前长度为2ᵏ的一段

算法复杂度:<O(NlogN), O(1)>

#include<bits/stdc++.h> using namespace std; class ST { public: ST(int n,vector<int>&a):M(n+1,vector<int>((int)log2(n)+1)) { pre(a); } void pre(vector<int>&a) { //初始化 int n = a.size() - 1; for (int i = 1; i <= n; i++) { M[i][0] = i; } //预处理M数组 for (int j = 1; (1 << j) <= n; j++) {//枚举区间长度 for (int i = 1; (i+(1<<j)-1)/*保证右端点不越界*/ <= n; i++) {//枚举起点 int tmp = (1 << (j - 1));//一半长度 if (a[M[i][j - 1]] >= a[M[i + tmp][j - 1]]) { M[i][j] = M[i][j - 1]; } else { M[i][j] = M[i + tmp][j - 1]; } } } } int search(int l, int r,vector<int>&a) { int k = log2(r - l + 1); int tmp = (1 << k); return max(a[M[l][k]], a[M[r-tmp+1][k]]); } public: //M:从i位置开始,往后2^j的RMQ vector<vector<int>>M; }; int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n, m; cin >> n >> m; vector<int>a(n+1); for (int i = 1; i <= n; i++) { cin >> a[i]; } ST s(n,a); while (m--) { int l, r; cin >> l >> r; cout<<s.search(l, r, a)<<'\n'; } return 0; }

ST表算法小结

常用于解决RMQ问题(最值,GCD,LCM等等)

适用于静态数据的查询(不支持修改),经过一次O(nlog2n)的离线预预处理之后,单次查询O(1)

所以,ST算法尤其适用于查询量很大很大的问题。

例题

数列连续区间gcd的特点?

单调性(非增)!!!!!

推荐算法:

ST求gcd+二分预处理所有gcd+map存储方案数

三.LCA

1.LCA概念

LCA,即最近公共祖先,是指这样一个问题:在有根树中,找出某两个节点u和v最近的公共祖先(换一种说法,离树根最远的祖先)。

生活中的的LCA:家族树状图

LCA和RMQ问题的关系?

2.符号约定

3.例子

4.LCA相关算法

(1)暴力算法

分别从节点 u 和 v 回溯到 T 的根节点,获取 u 和 v 到根节点的路径 P1,P2,其中 P1 和 P2 可以看成两条单链表。然后依次判断 P1 中的每个节点是否在 P2 中出现,第一个出现在 P2 中的节点即为第一个相交节点,即 LCAT(u,v)。

时间复杂度:O (N²)

(2)暴力算法2:

求两个链表的交点时,可以适用hash表优化,或者适用跳跃链表

时间复杂度:O(N)

(3)倍增算法

四.倍增算法解决LCA

倍增算法求LCA的P数组的含义

P[i][i]:表示从节点i往上跳2^i(节点i的第2^i个祖先)

倍增算法求LCA的DP预处理

P[i][0]=father[i];

P[i][j]=P[P[i][j-1]][j-1];

时间复杂度:O(nlogn)

为什么一开始要先要初始化P数组为-1,因为有可能越界(假如说一共有五层,从叶子节点能最多能跳2^2,但是如果我们从第二层,跳2^2就会越界)

倍增算法求LCA

首先,将 x 和 y 中深度较大的那个往上跳到和另一个深度相同。

此时,如果 x=y,则 LCA (x,y)=x,算法结束,否则进入下一步。

然后,同时向上倍增枚举一个 2 的幂的步长 2ⁱ,若 x 往上走 2ⁱ步与 y 往上走 2ⁱ步不为同一个点(没跳过),则将它们同时往上走 2ⁱ步,如果为同一个点,不跳,因为只能说明是祖先,但不一定是最近公共祖先。循环类似处理(i从log2(deep(u))向下取整,逐步缩小 i)

最后,你会发现,x和y一定跳到了最近公共祖先的下一层

时间复杂度:<O (NlogN), O (logN)>

注意:LCA 倍增跳跃,必须从大到小枚举(二进制拼凑),比如说9,如果从大到小枚举就拆成8和1,但是如果从小到大枚举,就会拆成1,2,4(凑不出来8),错误的贪心方式

五.LCA 到 RMQ 的规约

LCA和RMQ问题本质相同

我们可以在线性时间里将 LCA 问题规约到 RMQ 问题。因此,每一个解决 RMQ 的算法都可以解决 LCA 问题。从树 T 根节点开始,DFS 遍历得到 2n−1 个顶点组成的序列(欧拉回路)如下表:

1 2 1 3 5 3 6 8 6 9 6 3 7 10 12 10 13 10 7 11 7 3 1 4 1

如果我们想要求任意两点的最近公共祖先,实际上就是求两点间dfs序中深度最小的那个节点,两点间dfs序是连续数组,之后求连续数组的深度的最小值,我们可以适用st表来解决

六.例题

解题思路:

注意:

http://www.jsqmd.com/news/764275/

相关文章:

  • LIN总线报文实战:从示波器波形到CANoe/LINalyzer的完整分析流程
  • nodejs后端服务如何集成多模型api以提升功能弹性
  • STM32H745双核调试血泪史:一个焊错的电感,如何让我一周无法复位和下载程序
  • 2026智慧工厂室内定位管理系统推荐:厂区人员定位与可视化平台 - 品牌2025
  • 终极指南:如何免费解锁魔兽争霸3帧率限制,实现180帧流畅体验
  • 小程序商城哪个好用?2026新手商家避坑选购攻略 - FaiscoJeff
  • NBTExplorer:免费终极Minecraft数据可视化编辑器完整指南
  • 2026 陕西安防监控安装维护保养公司榜单【TOP5】全省上门维保服务商推荐 - 深度智识库
  • 告别脚手架恐惧症:用Umi Max + Ant Design Pro 5分钟搞定企业级React后台
  • 昆山隆广金属制品:姑苏区正规的金属制品批发公司选哪家 - LYL仔仔
  • 在无SDK环境中使用curl调试大模型API的请求与响应
  • 2026测力传感器哪家好?广东犸力以严苛标准,成为行业一致好评品牌 - 品牌速递
  • #2026最新超纤皮革公司推荐!广东优质权威榜单发布,口碑靠谱佛山等地公司选择指南 - 十大品牌榜
  • ZYNQ项目实战:如何将你的Vivado硬件设计无缝集成到Petalinux工程?HDF文件导入与配置避坑指南
  • 时间线维护技术
  • Linux 目录操作 C/C++ 开发笔记
  • 从4秒到无限:Runway Gen2免费版‘拼贴长视频’实战指南(附剪辑思路)
  • 告别环境冲突:用Docker Compose编排Superset全家桶(含PostgreSQL与Redis)
  • 哪家服务商真空设备检测设备齐全?真空技术实力雄厚的服务商推荐 - 品牌推荐大师
  • 云原生进阶方向原理与实战
  • 首驱 Yz Lite 质量靠谱吗?轻通勤小车的配置、价格与长期使用边界 - Top品牌推荐官
  • 终极指南:如何用SQLCoder快速将自然语言转换为SQL查询
  • 手把手教你用EWSA汉化版破解WiFi密码:从抓包到跑包的完整避坑指南
  • 深圳GEO优化服务商推荐(3家靠谱企业)| 本地生活+制造业全覆盖,附实战案例 - 品牌洞察官
  • 别再只把ONNX当个格式了!手把手教你用Python从零构建一个线性回归模型(附完整代码)
  • 基于Transformer的股票市场多因子量化选股模型,深度解析:基于Transformer的股票市场多因子量化选股模型
  • GIS小白也能看懂的实战:5步教你将ArcGIS里的等高线和水系完美导入CAD做规划图
  • 终极蓝光技术分析工具BDInfo完全指南:从入门到精通
  • 热脱附设备选购关注点:品质好、性能强的品牌 - 品牌推荐大师1
  • 苏州鼎轩废旧电子产品:太仓专业的线路板回收公司推荐几家 - LYL仔仔