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

RMQ与LCA学习笔记

在开始之前先提一下RMQ与LCA这两个东西有什么关系
对于一个序列,对它构建出一颗笛卡尔树之后,两个点的LCA就是原序列中这两个点之间的最大值/最小值(取决于建树时的比较方式)
而对于一棵树,求出来他的欧拉序之后,两个点的LCA,就是两个点在欧拉序第一次出现的位置之间的深度最小值的点
所以LCA问题和RMQ问题是可以相互转换的

RMQ

RMQ 即区间最值问题,根据情景的不同,我们可以给出不同的方法

静态区间最值问题

ST表

ST表,是一个处理静态可重复贡献问题的利器,区间最值显然是可以重复贡献的。
\(st_{i,k}\) 表示原序列中 \([i,i+2^k-1]\) 中的最值,显然初始化是 \(st_{i,0}=a[i]\)
我们可以将 \([i,i+2^k-1]\) 拆分成 \([i,i+2^{k-1}-1]\)\([i+2^{k-1},i+2^{k}-1]\) ,这两个区间中的最值显然是 \(st_{i,k-1}\)\(st_{i+2^{k-1},k-1}\)
所以我们从小到大枚举 \(k\) ,用 \(st_{i,k-1}\)\(st_{i+2^{k-1},k-1}\) 更新 \(st_{i,k}\)

for(int i=1;i<=n;i++)f[i][0]=read();
int t=log2(n);
for(int i=1;i<=t;i++){for(int k=1;k<=n-(1<<i)+1;k++){f[k][i]=max(f[k][i-1],f[k+(1<<(i-1))][i-1]);}
}//这里的i,k与上文中是反过来的

查询时,需要将 \([l,r]\) 拆成两个区间,使它们覆盖整个 \([l,r]\) ,可以发现 \(st_{l,\lfloor log_{2}{r-l+1}\rfloor}\) \(st_{r-2^{\lfloor log_{2}{r-l+1}\rfloor}+1,\lfloor log_{2}{r-l+1}\rfloor}\) 可以覆盖整个区间。

for(int i=1;i<=m;i++){int l,r;l=read();r=read();int k=log2(r-l+1);write(max(f[l][k],f[r-(1<<k)+1][k]));puts("");
}

预处理时间复杂度为 \(O(nlogn)\) ,单次查询复杂度为 \(O(1)\)

Method of Four Russians

就是人们常说的“四毛子”,这个算法在ST表的基础上进行了优化。
对序列进行分块,设块长为 \(B\) ,在块间建立ST表,时间复杂度为 \(O(\frac{N}{B}log{\frac{N}{B}})\),在块内建立ST表,时间复杂度为 \(O(\frac{N}{B}Blog{B})\).
查询时,若 \(l,r\) 在同一个块内,直接用块内的ST表查询,若 \(l,r\) 不在同一个块内,那么对于散块用块内的ST表查询,对于整块用块间的ST表查询。查询时间复杂度为 \(O(1)\)
\(B\)\(O(log_2{n})\) 时,预处理时间复杂度是 \(O(nloglogn)\)

struct FR{int ST[N/len+5][log2(N/len)+5],st[N][log2(len)+5];struct block{int l,r,ma;}b[N/len+5];void init(){for(int i=1;i<=id(n);i++){b[i].l=b[i-1].r+1;b[i].r=i*len;b[i].ma=0;}b[id(n)].r=n;for(int i=1;i<=id(n);i++){int t=log2(b[i].r-b[i].l+1);for(int k=b[i].l;k<=b[i].r;k++)st[k][0]=a[k],b[i].ma=max(b[i].ma,a[k]);for(int k=1;k<=t;k++){for(int j=b[i].l;j+(1<<k)-1<=b[i].r;j++){st[j][k]=max(st[j][k-1],st[j+(1<<(k-1))][k-1]);}				}}for(int i=1;i<=id(n);i++)ST[i][0]=b[i].ma;int t=log2(id(n));for(int i=1;i<=t;i++){for(int k=1;k+(1<<i)-1<=id(n);k++){ST[k][i]=max(ST[k][i-1],ST[k+(1<<(i-1))][i-1]);}}}int ask(int l,int r){int p=id(l),q=id(r);if(p==q){int t=log2(r-l+1);return max(st[l][t],st[r-(1<<t)+1][t]);}int x,y,z;int t=log2(b[p].r-l+1);x=max(st[l][t],st[b[p].r-(1<<t)+1][t]);t=log2(r-b[q].l+1);y=max(st[b[q].l][t],st[r-(1<<t)+1][t]);if(p+1>q-1)return max(x,y);t=log2(q-1-(p+1)+1);z=max(ST[p+1][t],ST[(q-1)-(1<<t)+1][t]);return max(x,max(y,z));}
}f;

但由于每次查询会使用3次ST表,所以常数会比直接建ST表大很多,在 \(n\) 较小的时候还是直接写ST表好

优化

\(l,r\) 不在一个块内时,考虑对于散块的查询,我们只需要考虑一个前缀或后缀的贡献就可以了,这样就可以将ST表调用次数降低到1次

O(N)-O(1)Rmq

四毛子的瓶颈在于当 \(l,r\) 在同一块时,没法做到快速处理。
这里给出一个基于状压的线性RMQ的做法
……

http://www.rkmt.cn/news/18409.html

相关文章:

  • mamba-硬件感知算法
  • gitee和github如何修改仓库名并且保持与原远程仓库的连接?(手把手教学) - 实践
  • 第十一篇
  • 如何在 Spring Boot 应用中配置多个 Spring AI 的 LLM 客户端
  • [Git] 放弃暂存区的修改
  • 前端里面transform和transition 属性的区别
  • 【MAC环境】安装多个 JDK - 指南
  • 第一个博客
  • k8s 主节点重启后 从节点 get 异常 - 教程
  • 训练笔记:博弈杂题
  • PyTorch 神经网络工具箱完全指南 - 详解
  • 2025表面瑕疵检测厂家TOP5推荐:表面瑕疵检测,薄膜瑕疵检测,瑕疵检测设备,瑕疵在线检测,铝箔瑕疵在线检测,外观瑕疵检测机,薄膜瑕疵检测仪,陶瓷膜瑕疵检测各种类型检测,精准高效的质量守护
  • 深入解析:如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘tokenizers’ 问题
  • Microsoft Office不小心卸载或重装系统后,如何重新安装 ... - sherlock
  • HTTPS 抓包乱码怎么办?原因剖析、排查步骤与实战工具对策(HTTPS 抓包乱码、gzipbrotli、TLS 解密、iOS 抓包) - 实践
  • 计算机视觉专家入选德国国家科学院
  • 2025 年工程管理软件/软件系统/软件App/软件平台/工程管理软件和验房系统公司/企业推荐榜:数字化转型下的实用选型指南
  • solutions
  • 完整教程:跨境必看:TikTok Ads广告竞价策略分享
  • 安装与配置MySQL 8 on Ubuntu,包括权限授予、数据库备份及远程连接
  • 04-最简单的字符设备驱动
  • 完整教程:手机可视化方案(针对浓度识别)
  • 用批处理材料实现Excel和word文件的重造
  • 实用指南:Linux编译SRS并测试RTMP流
  • HTML应用指南:利用POST请求获取全国索尼体验型零售店位置信息 - 详解
  • 离线安装 mysql
  • 为什么不该用 Double 表示金额及解决方案
  • 实用指南:WXML 编译错误修复总结
  • Vue.use(Vuex)
  • MyBatis 中的动态 SQL 的相关使用方法(Javaee/MyBatis) - 教程