【数据结构】ST 表与 RMQ 算法

本文参考【朝夕的ACM笔记】数据结构-ST表

在练习线段树的过程中经常会感叹代码怎么这么长啊啊啊懒标记怎么这么难传啊啊啊

于是在得知有一种代码量远小于线段树的算法时、、、(其实是因为做到了[SCOI2007] 降雨量

就是ST表啦~

在什么情况下可以用ST表代替线段树呢?

不需要区间修改可重复贡献问题

不需要区间修改很好理解,什么叫做可重复贡献呢?

我们知道,求一个数组的最大值(比如说长度为10的数组),我们可以先求前六个数的最大值,再求后七个数的最大值,最后求这两个最大值的最大值,虽然这中间有重复的元素,但是对最终的最大值结果不会有影响,这就叫做可重复贡献问题。

但是如果我们要求一个数组中所有元素的和(还是比如说长度为10的数组),我们就不能用前六个元素的和加上后七个元素的和了,这就叫做不可重复贡献问题。

常见的可重复贡献问题包括:求区间最大/小值区间按位和/或区间gcd

怎么构建ST表呢?

ST表是一种基于倍增算法的数据结构

我们设f[i][j]表示区间 [ i , i + 2 j − 1 ] [i, i + 2^j - 1] [i,i+2j1] 的最大值,因此f[i][0]表示的就是第 i 个元素本身了

由倍增思想,区间 [ i , i + 2 j − 1 ] [i, i + 2^j - 1] [i,i+2j1] 可以被我们拆成两个长度为 2 j − 1 2^{j - 1} 2j1 的子区间,所以可以的到递推式 f [ i ] [ j ] = m a x ( f [ i ] [ j − 1 ] , f [ i + 2 j − 1 ] [ j − 1 ] ) f[i][j]=max(f[i][j - 1], f[i + 2^{j-1}][j-1]) f[i][j]=max(f[i][j1],f[i+2j1][j1]),因此先枚举 j j j,再枚举 i i i,就可以得到 f [ i ] [ j ] f[i][j] f[i][j] 的值了

怎么查询区间信息呢?–> RMQ算法

如果我们想知道 [ l , r ] [l, r] [l,r] 的最值,我们可能会输出 f [ l ] [ x ] f[l][x] f[l][x], l + 2 x − 1 = r l+2^x-1=r l+2x1=r,这样解出x,会发现 x = l o g 2 ( r − l + 1 ) x=log_2(r-l+1) x=log2(rl+1),这样得到的 x 就不一定是个整数了,向下取整的话可能会使区间有所损失

这时可重复贡献的性质就发挥作用了,我们把要查询的区间 [ l , r ] [l,r] [l,r] 分成长度为 ⌊ x ⌋ \lfloor{x}\rfloor x 两部分,一部分以 l 开头,一部分以 r 结尾,也就是 [ l , l + 2 x − 1 ] [l, l+2^x-1] [l,l+2x1] [ r − 2 x + 1 , r ] [r-2^x+1,r] [r2x+1,r],只要找到这两个区间的最大值,再取最大值,就可以得到整个区间的最大值了

时间复杂度

预处理 O ( n l o g n ) O(nlogn) O(nlogn)
查询 O ( 1 ) O(1) O(1)

板子

#include <bits/stdc++.h>using namespace std;int f[100005][21];
int logn[100005], n, m;void pre() // 预处理log 防止查询时T
{logn[1] = 0, logn[2] = 1;for (int i = 3; i <= n; i++)logn[i] = logn[i / 2] + 1;
}
int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m;pre();// 输入数组本身for (int i = 1; i <= n; i++) cin >> f[i][0];for (int j = 1; j <= 21; j++) // 2的21次方满足两百万数据 数据变大上限也要变大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 -- ){cin >> l >> r;// RMQ查询int lg = logn[r - l + 1];int ans = max(f[l][lg], f[r - (1 << lg) + 1][lg]);cout << ans << '\n';}
}

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

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

相关文章

Web进阶

身份认证 当我们在使用互联网时&#xff0c;经常会遇到一些需要身份验证或者保持用户状态的情况。为了实现这些功能&#xff0c;常用的方法有使用cookie、session和token。 Cookie&#xff08;HTTP Cookie&#xff09;&#xff1a; Cookie是服务器发送到用户浏览器并保存在用户…

STM32-LCD中英文显示及应用

目录 字符编码 ASCII码&#xff08;8位&#xff09; 中文编码&#xff08;16位&#xff09; GB2312标准 GBK编码 GB18030标准&#xff08;32位&#xff09; Big5编码 Unicode字符集和编码 UTF-32&#xff08;32位&#xff09; UTF-16&#xff08;16位/32位&#xff0…

二十三、设计模式之组合模式![

目录 二十三、设计模式之组合模式能帮我们干什么&#xff1f;主要解决什么问题&#xff1f;优缺点优点缺点&#xff1a; 使用的场景理解实现角色组合模式 总结 魔战已经完结。成功登顶。占领敌军最高峰。 二十三、设计模式之组合模式 “组合模式”也被称为“部分整体模式”该…

方舟生存进化ARK个人服务器搭建教程保姆级

方舟生存进化ARK个人服务器搭建教程保姆级 大家好我是艾西&#xff0c;在很久之前我有给大家分享过方舟生存进化的搭建架设教程&#xff0c;但时间久远且以前的教程我现在回头看去在某些地方说的并不是那么清楚。最近也是闲暇无事打算重新巩固下方舟生存进化的搭建架设教程&…

Vue 路由传参和获取参数的方法

在使用 Vue 进行开发时&#xff0c;路由传参是非常常见且重要的功能。通过路由传参&#xff0c;我们可以在不同的页面之间传递数据&#xff0c;以实现更灵活的交互和功能。 Vue 提供了多种方法来实现路由传参和获取参数的操作。下面将介绍两种常用的方法&#xff1a; 1. 动态…

rpc入门笔记0x01

syntax "proto3"; // 这是个proto3的文件message HelloRequest{ // 创建数据对象string name 1; // name表示名称&#xff0c;编号是1 }生成python文件 安装grpcio和grpcio-tools库 pip install grpcio #安装grpc pip install grpcio-tools #安装grpc tools生成…

LuatOS-SOC接口文档(air780E)--libcoap - coap数据处理

libcoap.new(code, uri, headers, payload) 创建一个coap数据包 参数 传入值类型 解释 int coap的code, 例如libcoap.GET/libcoap.POST/libcoap.PUT/libcoap.DELETE string 目标URI,必须填写, 不需要加上/开头 table 请求头,类似于http的headers,可选 string 请求体…

argparse模块介绍

argparse是一个Python模块&#xff1a;命令行选项、参数和子命令解析器。argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义了所需的参数&#xff0c;而 argparse 将找出如何从 sys.argv &#xff08;命令行&#xff09;中解析这些参数。argparse 模块还会自动生成…

B-3:Web安全之综合渗透测试

B-3:Web安全之综合渗透测试 任务环境说明: 服务器场景:Server2104(关闭链接) 服务器场景用户名、密码:未知 1.通过URL访问http://靶机IP/1,对该页面进行渗透测试,将完成后返回的结果内容作为FLAG值提交; 通过访问IP/1,查看源代码发现flagishere,访问后发现什么也没…

【RabbitMQ】常用消息模型详解

文章目录 AMQP协议的回顾RabbitMQ支持的消息模型第一种模型(直连)开发生产者开发消费者生产者、消费者开发优化API参数细节 第二种模型(work quene)开发生产者开发消费者消息自动确认机制 第三种模型(fanout)开发生产者开发消费者 第四种模型(Routing)开发生产者开发消费者 第五…

jvm摘要

第 2 章 Java 内存区域与内存溢出异常 2.2 运行时数据区域 程序计数器-线程私有:是一块较小的内存空间&#xff0c;它可以看作是当前线程所执行的字节码的行号指示器。 程序计数器是唯一一个没有规定任何OutOfMemoryError 情况的区域。 Java 虚拟机栈-线程私有:用于执行Java …

悟空crm安装搭建 报错[0] RedisException in Redis.php line 56问题处理办法

相信很多朋友进行安装悟空crm的时候 提示错误&#xff1a; [0] RedisException in Redis.php line 56 Connection refused 不知道怎么样处理是吧~~~ $this->options array_merge($this->options, $options);}# redis 密码$password config(cache.password);if (!empty…

(二开)Flink 修改源码拓展 SQL 语法

1、Flink 扩展 calcite 中的语法解析 1&#xff09;定义需要的 SqlNode 节点类-以 SqlShowCatalogs 为例 a&#xff09;类位置 flink/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlShowCatalogs.java 核心方法&#xff1a; Override pu…

【C++】priority_queue仿函数

今天我们来学习C中另一个容器适配器&#xff1a;优先级队列——priority_queue&#xff1b;和C一个重要组件仿函数&#xff1a; 目录 一、priority_queue 1.1 priority_queue是什么 1.2 priority_queue的接口 1.2.1 priority_queue使用举例 二、仿函数 三、关于priority…

文件包含漏洞(1),文件包含漏洞的利用原理

文件包含漏洞利用的原理 一, 本地文件包含 1. 漏洞利用条件: 在默认情况下, php.ini配置文件中 allow_url_fopenOn 是开启状态. 服务器php脚本中的 include include_once require require_once 等函数用于包含文件中的代码, 如果参数是用户可控的, 则可能被利用来执行系统命…

Linux中的调度策略及其工作

对于操作系统来讲&#xff0c;它面对的 CPU 的数量是有限的&#xff0c;干活儿都是它们&#xff0c;但是进程数目远远超过 CPU 的数目&#xff0c;因而就需要进行进程的调度&#xff0c;有效地分配 CPU 的时间&#xff0c;既要保证进程的最快响应&#xff0c;也要保证进程之间的…

Docker GitLab-Runner安装

Docker GitLab-Runner安装 GitLab-Runner安装 问题合集GitLab 域名的配置修改Runner容器内注册失败&#xff0c;提示 dial tcp: lookup home.zsl0.com on 192.168.254.2:53: no such host GitLab-Runner 安装 拉去gitlab/gitlab-runner镜像 docker pull gitlab/gitlab-runne…

GoLand设置GOROOT报错The selected directory is not a valid home for Go SDK

在设置GOROOT时&#xff0c;点击选择安装目录后&#xff0c;出现如下图的提示&#xff1a;The selected directory is not a valid home for Go SDK 进入Go的安装目录&#xff0c;如D:\Go\src\runtime\internal\sys&#xff0c;打开zversion.go文件&#xff0c;加上自己的版本号…

适用于 Windows 10 和 Windows 11 设备的笔记本电脑管理软件

便携式计算机管理软件使 IT 管理员能够简化企业中使用的便携式计算机的部署和管理&#xff0c;当今大多数员工使用Windows 笔记本电脑作为他们的主要工作机器&#xff0c;他们确实已成为几乎每个组织不可或缺的一部分。由于与台式机相比&#xff0c;笔记本电脑足够便携&#xf…

Git的远程仓库

Git的远程仓库 添加远程仓库从远程库克隆 添加远程仓库 你在本地创建了一个Git仓库后&#xff0c;又想在GitHub创建一个Git仓库&#xff0c;并且让这两个仓库进行远程同步&#xff0c;这样&#xff0c;GitHub上的仓库既可以作为备份&#xff0c;又可以让其他人通过该仓库来协作…