数据结构——RMQ(ST表)问题

news/2024/10/6 1:19:49/文章来源:https://www.cnblogs.com/RainPPR/p/18288455

数据结构——RMQ(ST表)问题

问题描述

对于序列 \(A[1\dots n]\),有 \(m\) 组询问 \(\langle l,r\rangle\),求 \(\max_{i=l}^rA_i\)

我们下面使用 \(\mathcal O(A)\sim\mathcal O(B)\) 表示预处理 \(\mathcal O(A)\),单次询问 \(\mathcal O(B)\) 的时间复杂度。

线段树解法

时间复杂度:\(\mathcal O(n)\sim\mathcal O(\log n)\)

空间复杂度:\(\mathcal O(n)\)

#include <bits/stdc++.h>using namespace std;constexpr int N = 2e5 + 10;int n, a[N];#define ls(x) ((x) << 1)
#define rs(x) ((x) << 1 | 1)int seg[N << 2];void push_up(int k) {seg[k] = max(seg[ls(k)], seg[rs(k)]);
}void build(int k = 1, int l = 1, int r = n) {if (l == r) return void(seg[k] = a[l]);int mid = l + r >> 1;build(ls(k), l, mid);build(rs(k), mid + 1, r);push_up(k);
}int query(int p, int q, int k = 1, int l = 1, int r = n) {if (l >= p && r <= q) return seg[k];int mid = l + r >> 1;if (p > mid) return query(p, q, rs(k), mid + 1, r);if (q < mid + 1) return query(p, q, ls(k), l, mid);else return max(query(p, q, ls(k), l, mid), query(p, q, rs(k), mid + 1, r));
}signed main() {ios::sync_with_stdio(false);cin.tie(nullptr), cout.tie(nullptr);cin >> n;copy_n(istream_iterator<int>(cin), n, a + 1);build();int q, l, r; cin >> q;while (q--) cin >> l >> r, cout << query(l, r) << endl;return 0;
}

修改复杂度 \(\mathcal O(\log n)\)

ST 表

ST 表可以做到 \(\mathcal O(n\log n)\) 预处理,\(\mathcal O(1)\) 求出序列区间最大值。

按照最基础的思想,设 \(f(i,j)\) 表示区间 \([i,j]\) 的最大值,考虑上述倍增思想。

重新设计状态,

\(f(i,j)\) 表示区间 \([i,i+2^j-1]\) 的最大值,也就是从 \(i\) 开始的 \(2^j\) 个数。

考虑这样子递推的边界,

  • 显然 \(f(i,0)=a_i\)
  • 显然 \(f(i,j)=\max\{f(i,j-1),f(i+2^{j-1},j-1)\}\)

这么折半的预处理,可以做到 \(\mathcal O(n\log n)\) 的复杂度。

考虑查询,如果我们按照朴素的思想去处理的话,也是 \(\mathcal O(n\log n)\) 的,但是

有一个很简单的性质,\(\max\{x,x\}=x\),这意味着我们可以重复计算一个区间的最大值。

于是,我们可以把区间中一部分重复的区间跳过,直接去计算:

能覆盖整个区间的两个左右端点上的整个区间,就可以做到 \(\mathcal O(1)\)

除 RMQ 以外,还有其它的「可重复贡献问题」。例如「区间按位与」、「区间按位或」等。

ST 表能较好的维护「可重复贡献」的区间信息(同时也应满足结合律),时间复杂度较低。

可重复贡献问题是指满足 \(x\operatorname{opt} x=x\) 的运算对应的区间询问。

例如,\(\max(x,x)=x\)\(\operatorname{gcd}(x,x)=x\),等等。

所以 RMQ 和区间 GCD 就是一个可重复贡献问题,像区间和就不具有这个性质。

如果预处理区间重叠了,则会导致重叠部分被计算两次,这是我们所不愿意看到的。

#include <bits/stdc++.h>using namespace std;constexpr int N = 2e5 + 10;
constexpr int K = 20;int n, a[N];int st[N][K];#define pow2(x) (1 << (x))void build() {for (int i = 1; i <= n; ++i) st[i][0] = a[i];for (int k = 1; k < K; ++k) for (int i = 1; i + pow2(k) - 1 <= n; ++i) st[i][k] = max(st[i][k - 1], st[i + pow2(k - 1)][k - 1]);
}int query(int p, int q) {int k = log2(q - p + 1);return max(st[p][k], st[q - pow2(k) + 1][k]);
}signed main() {ios::sync_with_stdio(false);cin.tie(nullptr), cout.tie(nullptr);cin >> n;copy_n(istream_iterator<int>(cin), n, a + 1);build();int q, l, r; cin >> q;while (q--) cin >> l >> r, cout << query(l, r) << endl;return 0;
}

不支持修改(复杂度很差)。

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

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

相关文章

[Leetcode]经典算法

检测环 快慢指针法是一种用于检测链表中是否存在环的有效方法,同时也可以找到环的起点。该方法的原理基于两个指针在链表上同时移动,其中一个移动得更快,而另一个移动得更慢。检测环的存在:使用两个指针,一个称为快指针(fast),一个称为慢指针(slow)。 在每一步中,快…

关于import multiprocessing引用出错

关于import multiprocessing引用出错 0. 原因 当前文件名与python包体中关键词出现同名,导致循环引用 1. 排查过程 问题代码 import timefrom multiprocessing import Process, Queue # 这里提示错误def producer(queue):queue.put("a")time.sleep(2)def consumer(q…

进程信号

进程信号的产生,本质,进程信号的操作,进程信号的底层实现,以及阻塞信号,屏蔽信号1. 信号的产生 1.1 信号概念在生活中有很多的信号在我们身边围绕,例如红绿灯,发令枪,上课铃等等 在接受到信号,我们可以做出三种动作 1.立马去做对应信号的事情 2.等一会再做,有自己的…

24-暑假软件工程日报(7_7)

工作时间:7月7日 14:00-17:00 工作内容: 基本完成第二阶段大程序构建 代码:#include <cstring> #include <iostream> #include <list> #include <math.h> #include <queue> #include <stack> #include <stdio.h> #include <st…

[CISCN2019 华北赛区 Day2 Web1]Hack World

进入题目 输入数字1数字20对select 空格 union or 等等测试发现没有过滤select 空格也被过滤 注意不能单独测试用亦或运算 1^0为真 尝试0^if((ascii(substr((select(flag)from(flag)),1,1))=100),0,1) 回显正常根据回显判断正误 编写脚本爆破,由于该网站请求太快会报429,请求…

CubeMx的部分配置显示不出来

现象描述:CubeMx的部分配置显示不出来 处理方法:(1)继续进行其他配置,给工程起名字,并生成代码;(2)关闭CubeMx后再次打开

[CISCN2019 华东南赛区]Double Secret

进入题目由于请求不能过快,目录扫描工具失效可写脚本, 根据题目两个secret,猜测有serect目录 访问猜测还有一个secret参数随意输入发现源码泄露 注意到有flask,考虑python模板注入 注意到发现rc4加密 找师傅的加密脚本 import base64 from urllib.parse import quote def rc4…

[CISCN2019 华东南赛区]Web11

进入题目注意到xff 在url处随意输入目录xff随之变化 注意下放smarty是php模板 猜测xff为模板注入点 如下用if标签看到回显得到flag flag{6efda977-94fb-4d30-8668-fe28458ec2bf}

game1

进入题目发现是一个游戏发现有一个score.php的发包 发现有分数等 对比不同分数的包发现sign值都有ZM后疑似为base64于是将分数改为较高的分,ZM+base64 尝试要补一个=得到flag

[CISCN 2019 初赛]Love Math

进入题目,直接源码 代码审计、看师傅wp有黑名单字符过滤,有白名单函数过滤 于是用编码绕过,利用eval函数执行命令,system(cat /flag.txt) base_convert(a,b,c) //将数值a按b进制转换为c进制 dechex //将10进制转成16进制 hex2bin() //16进制转成字符串 base_convert(37907…

babyweb国赛华东北

进入题目目录扫描 扫出ssrf.php 发现url尝试用file协议访问/flag.txt拿到flag

人脸识别签到系统一站式开发【基于Pyqt5的CS架构软件】

人脸识别签到系统:课堂签到,上班打卡,进出门身份验证。 功能:人脸录入,打卡签到,声音提醒,打卡信息导出,打包exe文件人脸识别签到系统 1、运用场景 课堂签到,上班打卡,进出门身份验证。 2、功能架构 人脸录入,打卡签到,声音提醒,打卡信息导出:3、技术栈 python3.8…