hello大家好,今天是2025年8月23日,我要来给大家分享的是一个高阶数据结构---ST表。

一:引入

1.RMQ问题:

对于一个长度为 n 的序列,有 m 次查询操作,每次查询为一个区间 [l,r] 的最大值(最小值)。

上述问题可以用线段树来解决。但是杀鸡焉用宰牛刀,对于这种静态问题,我们可以使用代码量更少的方式来解决------ST表

2.ST表:

ST表(Sparse Table,稀疏表)是一种基于动态规划和倍增思想实现的数据结构形式上是一张二维表格ST表通过预处理一些信息,从而快速处理区间查询。(类似前缀和数组~)其中,预处理的时间复杂度为 O(n * log n),查询操作为 O(1)由于在查询前需要预处理出一些信息,因此ST表基本上只能解决静态问题。

ST表

将信息预处理完毕之后,对于查询操作只需要在这张二维表格中拿值就可以了。

这里解释一个名词:静态问题---以数组操作为例:

有静态问题就会有动态问题,静态问题就是只有查询操作没有修改操作,或者查询操作是在所有修改操作全部结束之后进行。相比之下,动态问题就是修改操作和查询操作交叉进行。

ST表能够解决的问题(静态问题)线段树绝大多数都可以解决,线段树能解决的问题(静态问题 & 动态问题)ST表就不一定可以解决。

3.ST表维护的信息:

ST表维护的信息需要满足结合律和可重复贡献。(例如区间最值以及区间gcd

这里借助一张图解释一下什么是结合律和可重复贡献。

如果不满足结合率和可重复贡献,ST表就不能解决。例如区间和以及区间乘积。

二:ST表的实现

计算机中的 log 默认是下取整的,在这里提前说一下,下面就不过多赘述了。

1.ST表维护信息的方式:

对于一个长度为 n 的序列,有 m 次查询操作,每次查询为一个区间 [l,r] 的最大值。

由于区间最值不满足可差性,因此不能像前缀和数组一样搞一张一维表格来预处理某些区间的信息。由于二维表格可以直接用来表示区间,那么可以尝试用二维的表格来预处理,一种直接的方式就是:f[i][j] 表示区间 [i, j] 的最值。

这种方式肯定是可以解决问题的。但是,RMQ 问题的数组一般都是 1e5~1e6 级别的长度,这张二维表格根本无法创建出来(空间溢出)。

我们尝试使用倍增的思想 2^{j} = 2^{j - 1} + 2 ^ {j - 1} 优化一下状态表示:

f[i][j] 表示:从 i 位置开始,长度为 2^j 的区间中,所有元素的最值。

以数组 a = 【5,2,4,6,1,7,5,0,9,3】为例,我们会用下述方式维护区间最大值信息。

这就是稀疏表的由来,并不是把所有的区间信息存下来,只存长度为 2^j 的区间信息。

优化之后,第二维空间大小 n 只需保证 2^n >= N 就行。25~30就足够了。可见,这个优化是非常有效的。

2.ST表的查询

预处理工作结束之后,我们能否使用预处理出的信息快速查询区间最值呢?

比如,我们要查询区间【l,r】的最大值:

根据状态表示,我们只需要先求出 k = log(2)(r - l + 1)(下取整),然后再从 f[l][k] 和

f[r - (1 << k) + 1][k] 两个格子中取最大值即可。

3.记忆区间起点和区间终点的技巧

  • 起点 + 区间长度 = 下一个区间的起点。
  • 终点 -  区间长度 = 上一个区间的终点。

4.ST表的实现

初始化

#include <iostream>
#include <cmath>using namespace std;
const int N = 1e5 + 10;int n;
int a[N], f[N][25]; // j ^ 25 >= N 就行  void init()
{for(int i = 1; i <= n; i++) f[i][0] = a[i];for(int j = 1; j <= log2(n); j++)for(int i = 1; i + (1 << j) - 1 <= n; i++)f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}

查询

int query(int l, int r)
{int k = log2(r - l + 1);return max(f[l][k], f[r - (1 << k) + 1][k]);
}

5.优化log(看题目情况)

如果查询次数过多,是会有一个 log 的开销的。如果把 log1~logn 全部预处理出来,那么查询操作的 k 就可以在 O(1)的时间得到。

对于对数运算,有如下公式:

因此可以通过递推,预处理出来所有的 log1 ~ logn。

加了优化的ST表:

#include <iostream>
#include <cmath>using namespace std;
const int N = 1e5 + 10;int n;
int a[N], f[N][25]; // j ^ 25 >= N 就行  
int lg[N];void init()
{lg[0] = -1; // 为了方便递推 lg[1] = lg[0] + 1 == 0 for(int i = 1; i <= n; i++){lg[i] = lg[i >> 1] + 1;f[i][0] = a[i];} for(int j = 1; j <= lg[n]; j++)for(int i = 1; i + (1 << j) - 1 <= n; i++)f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}int query(int l, int r)
{int k = lg[r - l + 1];return max(f[l][k], f[r - (1 << k) + 1][k]);
}

三:ST表模板题

题目一:【模板】ST表 && RMQ 问题

题目链接:【模板】ST表 && RMQ 问题

#include <iostream>
#include <cmath>using namespace std;const int N = 1e5 + 10;int n, m;
int f[N][25];int RMQ(int l, int r)
{int k = log2(r - l + 1);return max(f[l][k], f[r - (1 << k) + 1][k]);
}int main()
{scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++) scanf("%d", &f[i][0]);//初始化for (int j = 1; j <= log2(n); j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}}while (m--){int l, r; scanf("%d%d", &l, &r);printf("%d\n", RMQ(l, r));}return 0;
}

题目二:gcd 区间

题目链接:gcd 区间

#include <iostream>
#include <cmath>using namespace std;const int N = 1e3 + 10;int n, m;
int f[N][25];int gcd(int a, int b)
{return b == 0 ? a : gcd(b, a % b);
}int query(int l, int r)
{int k = log2(r - l + 1);return gcd(f[l][k], f[r - (1 << k) + 1][k]);
}int main()
{cin >> n >> m;for (int i = 1; i <= n; i++) cin >> f[i][0];for (int j = 1; j <= log2(n); j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){f[i][j] = gcd(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}}while (m--){int l, r; cin >> l >> r;cout << query(l, r) << endl;}return 0;
} 

四:ST表练习题

题目一:质量检测

题目链接:质量检测

这道题目的最优解是单调队列 O(n),但是我们这个专题是 ST 表,因此给出ST表的解法,下去之后也要尝试一下使用单调队列解决这道问题。

#include <iostream>
#include <cmath>
#include <cstring>using namespace std;const int N = 1e5 + 10;int n, m;
int f[N][25];int query(int l, int r)
{int k = log2(r - l + 1);return min(f[l][k], f[r - (1 << k) + 1][k]);
}int main()
{memset(f, 0x3f, sizeof f);cin >> n >> m;for (int i = 1; i <= n; i++) cin >> f[i][0];for (int j = 1; j <= log2(n); j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}}for (int i = 1; i + m - 1 <= n; i++){cout << query(i, i + m - 1) << endl;}return 0;
} 

题目二:Balanced Lineup G

题目链接:Balanced Lineup G

#include <iostream>
#include <cstring>
#include <cmath>using namespace std;const int N = 5e4 + 10;int n, m;
int f[N][28];
int g[N][28];int query(int l, int r)
{int k = log2(r - l + 1);return max(f[l][k], f[r - (1 << k) + 1][k])- min(g[l][k], g[r - (1 << k) + 1][k]);
}int main()
{cin >> n >> m;memset(g, 0x3f, sizeof g);for (int i = 1; i <= n; i++){cin >> f[i][0];g[i][0] = f[i][0];}for (int j = 1; j <= log2(n); j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);g[i][j] = min(g[i][j - 1], g[i + (1 << (j - 1))][j - 1]);}}while (m--){int l, r; cin >> l >> r;cout << query(l, r) << endl;}return 0;
}

今天的分享就到这里了~~,如果大家有疑问的话,欢迎下来之后和我沟通~~

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

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

相关文章

docker 安装nacos(vL2.5.0)

查找nacos 的所需的镜像版本 https://hub.docker.com/r/nacos/nacos-server/tags 拉取你所需的版本&#xff08;我们用v2.5.0&#xff09; docker pull nacos/nacos-server:v2.5.0 注意&#xff1a;因为我们需要挂载外配置文件 直接用volume 挂载目录 缺少初始文件报错 我们…

在github上通过dmca数字版权申诉侵权并删除侵权仓库

DMCA是什么&#xff1f; 《数字千年版权法案》&#xff08;DMCA&#xff09;为版权所有者&#xff08;包括软件开发人员&#xff09;创建了一个标准化的流程&#xff0c;要求GitHub删除侵权内容。您可以在美国版权局的官方网站上找到有关DMCA的更多信息。有关GitHub如何处理DM…

AI安全监控与人才需求的时间悖论(对AI安全模型、AI安全人才需求的一些思考)

当监控者与被监控者都是AI时&#xff0c;谁来监控监控者&#xff1f;这个看似简单的问题&#xff0c;却揭示了人工智能安全领域的根本性困境。一、问题的提出&#xff1a;当AI监控AI 随着大语言模型和生成式AI的快速发展&#xff0c;AI系统在元认知层面的能力越来越强&#xff…

AI模型部署 - 大型语言模型(LLM)推理部署中的实际显存评估

目录 第一部分:大型语言模型(LLM)推理显存占用的核心原理 1.1 显存占用的主要构成部分 1.2 影响显存占用的关键因素 1.2.1 模型架构:MoE vs. 稠密模型 1.2.2 上下文长度与并发数 1.2.3 部署方式与推理框架 1.2.4 硬件能力 第二部分:显存占用的精确计算方法 2.1 模…

【大语言模型 16】Transformer三种架构深度对比:选择最适合你的模型架构

【大语言模型 16】Transformer三种架构深度对比&#xff1a;选择最适合你的模型架构 关键词&#xff1a;Transformer架构&#xff0c;Encoder-Only&#xff0c;Decoder-Only&#xff0c;Encoder-Decoder&#xff0c;BERT&#xff0c;GPT&#xff0c;T5&#xff0c;模型选择&…

【LeetCode 热题 100】31. 下一个排列

Problem: 31. 下一个排列 文章目录整体思路完整代码时空复杂度时间复杂度&#xff1a;O(N)空间复杂度&#xff1a;O(1)整体思路 这段代码旨在解决经典的 “下一个排列” (Next Permutation) 问题。问题要求重新排列一个整数数组&#xff0c;使其变为字典序上的下一个更大的排列…

【Linux 进程】进程程序替换

文章目录1.进程替换的六个库函数2.execl1.进程替换的六个库函数 使用 man 3 execl 进行查询&#xff0c;3表示 Linux 中的3号手册&#xff0c;即为库函数&#xff08;例如C标准库中的库函数&#xff0c;printf&#xff0c;malloc&#xff09; man 1: 用户命令&#xff08;在sh…

ReasonRank: Empowering Passage Ranking with Strong Reasoning Ability

主要内容总结 本文提出了一种具有强推理能力的列表式段落重排序模型ReasonRank,旨在解决现有重排序模型在推理密集型场景(如复杂问答、数学问题、代码查询等)中表现不佳的问题,核心原因是这类场景缺乏高质量的推理密集型训练数据。 为解决这一问题,研究团队: 设计了自动…

不卡顿、不掉线!稳定可靠的体育赛事直播系统源码解析

在体育和电竞行业&#xff0c;实时直播系统已经成为平台的标配。无论是 OTT、比分直播网站&#xff0c;还是综合类体育社区&#xff0c;用户对直播体验的要求越来越高&#xff1a;不卡顿、不掉线、实时性强。那么&#xff0c;从技术角度出发&#xff0c;一个稳定可靠的 体育赛事…

三菱FX5U PLC访问字变量的某一位

三菱FX5U PLC气缸控制功能块 三菱FX5U气缸控制功能块(完整ST源代码+示例程序)_三菱fx5u标签气缸报警程序功能块-CSDN博客文章浏览阅读560次,点赞5次,收藏2次。如果机器包含100个气缸,我们只需要修改数组的元素数量就可以了,效率非常的高。待续....博途PLC 面向对象系列之“…

Java大厂面试全真模拟:从Spring Boot到微服务架构实战

Java大厂面试全真模拟&#xff1a;从Spring Boot到微服务架构实战 面试场景&#xff1a;某互联网大厂Java后端岗位&#xff0c;候选人谢飞机&#xff08;水货程序员&#xff09; 第一轮&#xff1a;基础与框架认知 面试官&#xff1a;你好&#xff0c;谢飞机&#xff0c;先简单…

Unity游戏打包——Mac基本环境杂记

1、安装 Homebrew若未安装&#xff0c;在使用 brew 命令时将提示 zsh: command not found: brew安装命令&#xff1a;/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"2、更换终端默认 Shell 为 zsh查看已安装的shell&#…

服务组件体系结构(SCA)全景解析

服务组件体系结构&#xff08;SCA&#xff09;全景解析SCA&#xff08;Service Component Architecture&#xff09;是 SOA 生态中专门用来“把服务拼起来并跑起来”的规范。它通过语言中立、协议可插拔、装配声明式三大能力&#xff0c;把“接口—实现—协议”彻底解耦&#x…

问:单证硕士含金量是否不足?

很多人认为花几万块钱读一个同等学历申硕&#xff0c;含金量并没有那么高&#xff0c;但事实却并非如此。今天我们从证书和学习的两个方面来聊一下同等学历申硕的含金量到底是如何的。一、单证含金量看以下几点&#xff1a;&#xff08;1&#xff09;国家认证与学信网可查 …

0.04% vs 0.1%:精度差一点,逆变器性能差距有多大?

一台光伏逆变器损失的功率可能仅仅源于0.3%的MPPT效率差距。这个足以影响产品竞争力的数字&#xff0c;可能并非算法优劣&#xff0c;而在于测试源头的精度选择&#xff1a;是0.04%还是0.1%&#xff1f;本文通过四大测试场景的量化对比&#xff0c;揭示不同的测试精度如何影响产…

Docker Hub 镜像一键同步至阿里云 ACR

&#x1f433; Docker Hub 镜像一键同步至阿里云 ACR 本脚本用于 从 Docker Hub 拉取镜像并推送到阿里云容器镜像服务&#xff08;ACR&#xff09;。 它通过 Python 的 docker SDK 封装了完整流程&#xff1a;拉取 → 重命名 → 登录 → 推送&#xff0c;并在控制台实时输出进度…

软考-系统架构设计师 计算机系统基础知识详细讲解

个人博客&#xff1a;blogs.wurp.top 一、计算机系统组成与多级层次结构 1. 冯诺依曼体系结构 (核心考点) 这是所有现代计算机的理论基础。核心思想是 “存储程序” 。 五大部件&#xff1a;运算器、控制器、存储器、输入设备、输出设备。工作流程&#xff1a;指令驱动。CP…

DLL文件丢失怎么办?这个修复工具一键搞定!

软件介绍&#xff08;文末获取&#xff09;是不是经常遇到这种情况&#xff1a;安装软件时提示缺少DLL文件&#xff1f;打开游戏时出现DLL错误&#xff1f;或者运行程序时突然崩溃&#xff1f;今天给大家推荐一款超好用的DLL修复工具——4DDiG DLL Fixer&#xff0c;一键解决所…

并发容器小结及ConcurrentSkipListMap介绍——并发系列(十一)

目录 概述 ConcurrentHashMap CopyOnWriteArrayList ConcurrentLinkedQueue BlockingQueue ConcurrentSkipListMap 设计目的 功能特性 与其他相关类对比 适用场景 概述 JDK提供的这些容器大部分在 java.util.concurrent 包中。我们这里挑选出了一些比较有代表性的并发…

蓝思科技半年净利超11亿,蓝思成绩单怎么分析?

8月26日&#xff0c;蓝思科技发布2025年半年度业绩报告&#xff0c;其中&#xff0c;净利润11.43亿元&#xff0c;同比增长32.68%。这份成绩单我们该怎么分析&#xff1a;首先&#xff0c;蓝思科技营收与利润双增长&#xff0c;成长能力持续凸显。报告期内&#xff0c;公司营业…