RMQ学习笔记

news/2025/3/3 23:13:34/文章来源:https://www.cnblogs.com/FrankWKD/p/18746903

RMQ学习笔记

前言:这个算法无论是从适配性还是长度来说都很有实力...💦

关于 RMQ

RMQ 是英文 Range Maximum/Minimum Query 的缩写,表示区间最大(最小)值。

详细信息

\(l-r\) 区间内的最大/最小数.

区间构造

  • 本质是DP.设 \(f[i][j]\)\(i\sim i+2^{j-1}\) 的区间最大值.特别地,\(f[i][0]=a[i]\).(一个数的最大值是它本身).
  • 状态转移方程: \(f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1])\).

区间查询

  • 设要查询的区间为 \([L,R]\) (包括LR)
  • \[k = log2(R-L+1) \]

  • \[res[L][R] = max(f[L][K],f[R-2^k+1][k]) \]

  • 注意:为保证精度,请自己推导 \(2^k\) ,而不是直接使用 \(log\) 函数.

时间复杂度: \(O(nlog_2n)\)

A. 超级记忆力

题目描述

小A同学拥有无与伦比的超级记忆力,他可以一次性记住很多数字。

为了考验一下小A同学的记忆力,王老师一次性给小A展示了 \(N\) 个整数。然后问了他 \(M\) 个问题,每个问题给定一个区间,要求小A同学说出这个区间中的最大数是多少?

为方便老师检验小A同学的答案是否正确,请你先编程求出正确的答案。

输入

第一行两个整数 \(N,M\) 表示数字的个数和要询问的次数;

接下来一行为 \(N\) 个数;

接下来 \(M\) 行,每行都有两个整数 \(X,Y\) 表示询问的区间。

数据范围:

\(1≤N≤10^5,1≤M≤10^6,1≤X≤Y≤N\)。数字不超过 C/C++ 的 int 范围。

解法:

  • 板子,没什么可说的.注意:要开scanf!
#include <bits/stdc++.h>
using namespace std;const int N = 1e5 + 10, L = 20;
int a[N], f[N][L];
int lg[N];
int n, m, x, y, k;
int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);}lg[1] = 0;for (int i = 2; i <= n; i++) lg[i] = lg[i / 2] + 1;for (int j = 0; j < L; j++) {for (int i = 1; i + (1 << j) - 1 <= n; i++) {if (j == 0)f[i][j] = a[i];elsef[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);}}while (m--) {scanf("%d%d", &x, &y);k = lg[y - x + 1];printf("%d\n", max(f[x][k], f[y - (1 << k) + 1][k]));}
}

B. 荣耀之战

题目描述

\(A\) 是一名游戏玩家,他正在玩一款叫做“荣耀之战”的游戏。在这个游戏中,他需要通过完成任务来提升自己的等级。

游戏地图上有 \(N\) 个排成一排的装备,每个装备都标注好了经验值和危险值,第 \(i\) 个装备的经验值为 \(V_i\) 危险值为 \(D_i\)

\(A\) 接到了一个任务,他需要在这 \(N\) 个装备中,选取连续的若干个装备,并使得这些装备的经验值总和不小于 \(K\)\(\ge K\))。同时要使得这些装备的最大的危险值尽可能的小。

请编程计算出,满足题意的方案中,最大的危险值最小是多少?

输入

\(1\) 行读入 \(2\) 个整数 \(N,K\)

接下来 \(N\) 行,每行读入 \(2\) 个整数 \(V_i,D_i\) ,分别表示每个装备的经验值和危险值。

数据范围

对于 \(100\%\) 的数据,满足 \(1 \le N \le 10^5\)\(1 \le V_i,D_i \le 10^9\)\(1 \le K \le 10^{18}\)

  • 要选出一个区间,使得他们在 \(V_i\ge K\) 的情况下 \(D_i\) 的总和最小.能够转化为: 选择 \(V_l+V_{i+1}+...+V_r \ge K\) 且 $D_l+D_{i+1}+...+D_r $ 最小.很容易想到用双指针来解决.注意:一定要让已经过去的数出队!!!
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int L = 20;
long long a[N];
long long lg[N], f[N][L];
long long n, m, v[N], w[N];
#define value long long
value max(value a, value b) {return a > b ? a : b;
}
value min(value a, value b) {return a < b ? a : b;
}
int main() {cin >> n >> m;for (int i = 1; i <= n; i++) {scanf("%lld%lld", &v[i], &w[i]);}lg[1] = 0;for (int i = 2; i <= n; i++) {lg[i] = lg[i / 2] + 1;}for (int i = 0; i < L; i++) {for (int j = 1; j + (1 << i) - 1 <= n; j++) {if (i == 0)f[j][i] = w[j];elsef[j][i] = max(f[j][i - 1], f[j + (1 << (i - 1))][i - 1]);}}long long r = 0, sum = 0;long long ans = INT_MAX;for (int l = 1; l <= n; l++) {while (r + 1 <= n and sum < m) {sum += v[++r];}if (sum >= m) {long longlen = lg[r - l + 1];ans = min(ans, max(f[l][len], f[r - (1 << len) + 1][len]));}sum -= v[l];  // 一定要注意让已经过去的数出队!!!!}printf("%lld\n", ans);
}

C.异或

题目内容

有一个长度为 \(N\) 的数列 \(A_1,A_2,\dots,A_n\)

请问该数列中任意取一个区间 \([L,R]\) 中,是否存在 \(2\) 个数,使得这两个数异或的结果为 \(T\)

请注意,本题会发起 \(M\) 次询问,对于每次询问的区间,如果能找到符合题意的数对,请输出 yes,否则请输出 no

输入

第一行包含三个整数 \(n, m, T\)

第二行包含 \(n\) 个整数,数字之间用空格隔开。

接下来的 \(M\) 行,每行有一个询问区间,每个询问区间包含 \(2\) 个整数 \(L,R\)

数据规模

对于 \(20 \%\) 数据, \(1 \leq n, m \leq 100\);

对于另外 \(40 \%\) 数据, \(1 \leq n, m \leq 1000\);

对于 \(100 %\) 的数据, \(1 \leq n, m \leq 10^5,0 \leq T < 2^{20},1\le L \le R \le n,0 \le a_i \le 2^{20}\)

思路

  • 首先,我们暴力肯定过不了.
  • 题目要求给定区间内是否有一对数.\(a,b\) 满足 \(a^b=T\)
  • 简单推到可得: \(a^T=b\) 是由上面式子转化而来的.
  • 我们随便列一组数据,并存储到 \(a\) 数组里面: \(a[]=\{2,1,3,4,2,3,2,3\}\)
  • 然后没个数异或 \(T\) 得: \(a_2[]=\{3,0,2,5,3,2,3,2\}\)
  • 然后在每个数的前面查找异或 \(T\) 后的数,如果找不到标记为 \(0\) :\(a_3[]=\{0,0,1,0,3,5,6,7\}\)
  • 如果要找的区间内对应的所有 \(a_3[i]\) 中有大于 \(L\) 而且小于 \(R\) 的数,那就成功了.输出 \(yes.\) 否则就是 \(no\) .
  • 这个找符合规定的数的过程可以使用RMQ.记录每个区间内的最小数然后方便之后查找,并且具有最优性.(不信可以试试不同的数据)

Extra T1 P2880 [USACO07JAN] Balanced Lineup G

没什么可说的,两次RMQ板子分别最大最小,还需要多打打板子题啊...好多小细节需要注意,但是大体上没什么难度.

#include <bits/stdc++.h>
using namespace std;const int N = 1e5 * 5 + 10, L = 20;
int f[N][L], a[N], lg[N];  // lg数组的本质就是求出两个下标之间的差值然后log2一下,所以直接开N就行
int fmi[N][L];
int n, q, l, r;int main() {cin >> n >> q;for (int i = 1; i <= n; i++) {cin >> a[i];}// 初始化lg数组lg[1] = 0;for (int i = 2; i <= n; i++) {lg[i] = lg[i / 2] + 1;}// 初始化最大值ST表for (int i = 0; i < L; i++) {  // i从0开始!!!!2^0也是正整数!!!!for (int j = 1; j + (1 << i) - 1 <= n; j++) {if (i == 0)  // 同上个注释f[j][i] = a[j];elsef[j][i] = max(f[j][i - 1], f[j + (1 << (i - 1))][i - 1]);}}// 初始化最小值ST表for (int i = 0; i < L; i++) {for (int j = 1; j + (1 << i) - 1 <= n; j++) {if (i == 0)fmi[j][i] = a[j];elsefmi[j][i] = min(fmi[j][i - 1], fmi[j + (1 << (i - 1))][i - 1]);}}// 构造完毕.while (q--) {cin >> l >> r;int len = lg[r - l + 1];int maxx = max(f[l][len], f[r - (1 << len) + 1][len]);int minn = min(fmi[l][len], fmi[r - (1 << len) + 1][len]);cout << maxx - minn << "\n";}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/893200.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

生意的本质是什么?几个关键概念的理解

生意的本质一句话理解 生意的本质可以理解为通过满足他人需求来实现价值交换的过程。其核心是围绕价值创造和价值交换来展开。满足需求:提供解决需求的产品或服务。 价值交换:人们参与交易,价值交换过程。可以看成是价值创造与交换的过程。底层逻辑:供需关系 供需关系 生意…

STM32实战——DHT11温湿度获取并展示

本博客详细介绍了DHT11数字温湿度传感器的工作原理、通信协议及其与STM32的接线方式,并提供了完整的驱动代码与示例程序,帮助读者实现温湿度数据采集与显示,适用于嵌入式开发者学习和参考。介绍 DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,包括…

Windows平台调试器原理与编写03.单步

调试器原理与编写03.单步-C/C++基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net 单步 TF - 置位(置1 复位就是置0) 单步步入 -- 遇到call便入单步步过 -- 遇到call不入区分一条指令是不是call指令: 通过反汇编引擎,反汇编出来是个 call 说明 就是 call指令 代码实现…

day14 服务管理篇的学习

day14 服务管理的学习 1.Linux的默认提供的服务 1. shhd 的命令 [root@linux-yzk ~]# netstat -tnlp | grep sshd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1137/sshd tcp 0 0 127.0.0.1:6010 0.0.0…

关于ADAC儿童安全座椅排名

ADAC官网地址 直接翻看排行榜, 注意, 分数越小,排名越靠前。 国内推荐使用 亚马逊中国这样的app或者网站进行购买,海外直邮。 避免在国内买到贴牌货, 国内, 懂得都懂, 5星批发部, 实际使用的和送检的不是同一种, AB货。当然不是所有的国内的商品都是AB货。ADAC不支持主…

六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性

六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性@目录六、MyBatis特殊的SQL6.1 模糊查询6.2 动态设置表名6.3 校验名称唯一性本人其他相关文章链接 六、MyBatis特殊的SQL 6.1 模糊查询方式1:select * from litemall_user where username like %${username}%(推…

AI生成代码测试,前端加后端

首先是话术, 让我们先理顺一下项目的逻辑,对于这样一个WEB管理系统界面,我们有多个思路,如功能模块化,或者前后端分离。 由于我们的MIS系统相对简单,我们可以将整个开发流程进行功能化细分。 首先,完成基础的环境配置。 需求描述: 请设计一个仓储管理系统原型系统,该系…

目前国内可用Docker镜像源汇总(截至2025年2月)

[目前国内可用Docker镜像源汇总(截至2025年2月) - CoderJia](https://www.coderjia.cn/archives/dba3f94c-a021-468a-8ac6-e840f85867ea) 在国内使用 Docker 的朋友们,可能都遇到过配置镜像源来加速镜像拉取的操作。然而,最近几个月发现许多曾经常用的国内镜像站(包括各种…

我的lua使用初体验

本文记录作者第一次使用lua的一次实践,主要借助lua来保证检查锁和释放锁的原子性使用lua实现检查和删除分布式锁的原子性很多时候出现并发问题的根本原因在于检查和操作不是同一个操作,不具有原子性,所以中间会被其他线程插一脚。所以我们需要有一种工具保证这两种操作的原子…

三剑客与正则系列-sed命令

1.概述核心功能:取行,过滤,替换修改文件内容 难点:后向引用(截取). sed stream editor流编辑器.2.格式命令 选项 详细格式 参数sed 选项 条件动作 文件找谁干啥找谁:条件,匹配哪一行,哪些行. 干啥:动作,增删改查. #显示文件的第3行 sed -n 3p /etc/passwd选项 说明-n 取消默认输…

加速PyTorch模型训练技巧

Pytorch-Lightning 可以在Pytorch的库Pytorch-lightning中找到我们在这里讨论的每一个优化。Lightning是在Pytorch之上的一个封装,它可以自动训练,同时让研究人员完全控制关键的模型组件。Lightning使用最新的最佳实践,并将你可能出错的地方最小化。 我们为MINST定义为Light…