通州网站建设是什么/南宁一站网网络技术有限公司
RMQ(Range Minimum/Maximum Query)
- RMQ解决的问题
- ST算法 O(nlogn)
- 线段树
- 例题
- 数列区间最大值
- 最敏捷的机器人
- 天才的记忆
- Frequent values
- 总结(ST和线段树对比)
RMQ解决的问题
RMQ是一个解决多个区间最值查询的算法,即区间最值查询;
如果我们要查询某一个区间内的最值,显然我们可以用暴力搜索的方式在O(n)的时间复杂度内获得结果,但是当我们要查询10000个不同区间内的最值时,我们如果依然采用暴力搜索的方式,那么时间复杂度就会变成O(mn),其中m指的是查询次数,n指的是数据个数。
RMQ算法的目标就是降低多区间最值查询问题的时间复杂度,一般还可以使用线段树求解,复杂度是O(mlogn) 。但还有一种更简便的ST算法,预处理复杂度是O(nlogn),查询O(1)。
RMQ四种解法
ST算法 O(nlogn)
ST(Sparse Table)即稀疏表,算法是通过动态规划思想实现的,他需要在O(nlogn)的时间复杂度内预处理出部分区间的最值,在O(1)的时间内获得一个区间的最值查询结果。总的时间复杂度被降到了O(nlogn)。
预处理 O(nlogn)
dp[i][j]表示数组第i个元素开始,长度为2^j的区间内的最值。
根据这种dp定义方式,我们可以轻松获得dp[i][j]的递推公式:
dp[i][j]=max(dp[i][j-1],dp[i+2^(j-1)][j-1]);
原理类似倍增,首先比较每2个元素的最值,然后再通过比较这2个最值,得到4个元素的最值,以此类推8个、16个……不断地枚举区间长度,,对每种区间长度求出所有不同起点的区间的最值。
代码实现:
void ST()
{//下标i最好是从1开始 for(int i=1;i<=n;i++) dp[i][0]=a[i]; //区间长度为1时最值就是自己 //int t=(int)(log(n) / log(2)); j<=t也可以 for(int j=1;pow(2,j)<=n;j++) //枚举区间的长度 ,必须先遍历j再遍历i {for(int i=1;i+pow(2,j)-1<=n;i++) //保证左右合并后的区间的r不超过最后下标n {dp[i][j]=max(dp[i][j-1],dp[i+pow(2,j-1)][j-1]);}}
}void ST()
{for(int i=1;i<=n;i++) dp[i][0]=a[i]; for(int j=1;1<<j<=n;j++) {for(int i=1;i+1<<j-1<=n;i++) //用左移的方式更快一些 {dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}}
}
查询 O(1)
预处理算法的每个区间除了第一个以外都是偶数,那万一他给个不符合条件的区间怎么办,也就是显然我们似乎不能直接一步从dp数组中得到问题的答案,这里我们采用的是从两个有重叠的区间中找到我们需要的答案,这两个重叠的区间一定会包含[l,r]区间内的所有元素
我们需要先算出不超过这个区间长度的 2^ t的t的最大值:log2(r−l+1) 。
那么这个区间的最大值就为 “从l开始的2^ t 个数” 和 “以r结尾的2^ t个数” 这两段的最大值较大的一个。即 max(f[l][t], f[r-(1<<t)+1][t])。
2^t是不超过区间长度r-l+1的最大的数,那2 ^(t+1)一定是超过r-l+1的,也就是前2 ^t个数和后2 ^t个数的和2 ^(t+1)个数的长度一定是大于等于区间长度r-l+1的,因此前后区间能够囊括这个区间内的所有数
代码实现:
//查询
LL query(LL l,LL r)
{LL t=log2(r-l+1);return max(dp[l][t],dp[r-(1<<t)+1][t]);
}
线段树
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。
例题
数列区间最大值
题目链接:https://www.acwing.com/problem/content/1272/
ST算法
思路分析:直接暴力求,明显的,最坏情况下时间复杂度为O(nm)=10^11,肯定超时
用ST算法来求,预处理O(nlogn)=10^7,查询O(m*1)=10 ^6不会超时
暴力超时代码:
#include<iostream>
using namespace std;
const int N=100005;
int a[N];
int n,m,x,y;
int main()
{scanf("%d %d",&n,&m);for(int i=1;i<=n;i++) cin>>a[i];for(int i=0;i<m;i++){scanf("%d %d",&x,&y);int max=0;for(int j=x;j<=y;j++){if(a[j]>max) max=a[j];}printf("%d\n",max);}return 0;
}
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL N=100005;
LL a[N];
LL n,m,x,y;
LL dp[N][20]; //2^20就足够大于n了//预处理
void ST()
{for(LL i=1;i<=n;i++) dp[i][0]=a[i];for(LL j=1;1<<j<=n;j++){for(LL i=1;i+(1<<j)-1<=n;i++){dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}}
}
//查询
LL query(LL l,LL r)
{LL t=log2(r-l+1);return max(dp[l][t],dp[r-(1<<t)+1][t]);
}
int main()
{scanf("%d %d",&n,&m);for(LL i=1;i<=n;i++) scanf("%d",&a[i]);ST();while(m--){scanf("%d %d",&x,&y);printf("%d\n",query(x,y));}return 0;
}
线段树算法
思路分析:
AC代码:
最敏捷的机器人
题目链接:https://www.acwing.com/problem/content/description/1273/
思路分析:就维护最大值和最小值数组即可
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
typedef long long LL;
LL a[N];
LL Max[N][20]; // 最大值
LL Min[N][20]; //最小值
int n,k;
int main()
{scanf("%d %d",&n,&k);for(int i=1;i<=n;i++) {scanf("%ld",&a[i]);Max[i][0]=a[i];Min[i][0]=a[i];}for(int j=1;1<<j<=n;j++){for(int i=1;i+(1<<(j-1))-1<=n;i++){Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);}}int t=n-k+1;for(int i=1;i<=t;i++){int l=i,r=i+k-1;int tmp=log2(k);printf("%d ",max(Max[l][tmp],Max[r-(1<<tmp)+1][tmp]));printf("%d\n",min(Min[l][tmp],Min[r-(1<<tmp)+1][tmp]));}return 0;
}
天才的记忆
题目链接:https://www.acwing.com/activity/content/problem/content/1795/
ST算法
跟上面两个题代码一样
线段树算法
Frequent values
题目链接:http://poj.org/problem?id=3368
ST算法
思路分析:首先需要对给出的区间进行一下处理,将连续的元素进行连续标号,对于标号后的数组,任意给出一个区间,可以将这个区间看做由两部分组成,前面部分是前一个连续数组遗留下来的一些元素,后面部分是多个属于区间内的连续元素组成的数组,最后取遗留下来的元素个数和后面多个连续数的最大的数量二者的最大值即可,也就是先找到这两部分的分界点:区间[i,j]内的第一个1的位置为k,答案就为max(k - i,RMQ(k,j));
AC代码:
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
const int N=100005;
int a[N];
int dp[N][20];
int n,q,t,pre,x,y;
void ST()
{for(int i=1;i<=n;i++) dp[i][0]=a[i];for(int j=1;1<<j<=n;j++){for(int i=1;i+(1<<j)-1<=n;i++){dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}}
}
int query(int l,int r)
{t=log2(r-l+1);return max(dp[l][t],dp[r-(1<<t)+1][t]);
}
int main()
{while(scanf("%d", &n) && n != 0){scanf("%d",&q);int pre=-100001;for(int i=1;i<=n;i++){scanf("%d",&t);if(t==pre) a[i]=a[i-1]+1;else a[i]=1;pre=t;}ST();while(q--){scanf("%d %d",&x,&y);int l=-1;for(int i=x;i<=y;i++){if(a[i]==1) {l=i;break;} //找到第一个1作为区间左部 }if(l!=-1) printf("%d\n",max(l-x,query(l,y))); //区间内有1 else printf("%d\n",y-x+1); //区间内没有1 }}return 0;
}/*
10 41 2 3 4 5 6 7 8 9 10 //下标
-1 -1 1 1 1 1 3 10 10 10 //所给数组 1 2 1 2 3 4 1 1 2 3 //连续标号后的数组
2 3 --1 待求区间内只有一组连续重复值,前面有上一组剩下的一个元素
1 10 -- 4 待求区间内有多组连续重复值,前面没有上一个组剩下的一些元素
5 10 --3 待求区间内有多组连续重复值,前面有上一组剩下的两个元素
4 6 --3 待求区间内没有新的连续重复值,只有前面上一组剩下的元素
0
*/
线段树算法
总结(ST和线段树对比)
当题目是离线的时侯使用ST算法更快,时间复杂度为O(nlogn),当题目是在线的时候直接使用线段树维护即可,因为线段树可以进行修改,单点修改维护也是logn,总的时间复杂度为O(nlogn+mlogn)
相关文章:

RMQ--区间最值问题(在更)
RMQ(Range Minimum/Maximum Query)RMQ解决的问题ST算法 O(nlogn)线段树例题数列区间最大值最敏捷的机器人天才的记忆Frequent values总结(ST和线段树对比)RMQ解决的问题 RMQ是一个解决多个区间最值查询的算法,即区间最值查询&…...

一篇文章搞懂Cookie
目录 1 什么是Cookie 2 创建Cookie 3 浏览器查看Cookie 3.1 浏览器查看Cookie的第一种方式 3.2 浏览器查看Cookie的第二种方式 4 获取Cookie 5 修改Cookie 6 Cookie编码与解码 6.1 创建带中文Cookie 6.2 读取带中文Cookie 6.3 获取中文Cookie请求效果 6.4 解决创建和…...

深入解读.NET MAUI音乐播放器项目(二):播放内核
播放控制服务 IMusicControlService: 播放控制类,用于当前平台播放器对象的操作,对当前所播放曲目的暂停/播放,下一首/上一首,快进快退(寻迹),随机、单曲模式等功能的控制。 播放控制类包含一…...

4.SpringWeb
一、创建项目LomBok:辅助开发工具,减少代码编写Spring Web:带上Spring MVC,可以做Web开发了Thymleaf: Web开发末班引擎(不常用)创建好,如下:static/ 放置静态资源的根目录templates/ 放置模板文件的根目录 二、资源配置…...

C++中的枚举与位域
枚举在传统 C中,枚举类型并非类型安全,枚举类型会被视作整数,则会让两种完全不同的枚举类型可以进行直接的比较(虽然编译器给出了检查,但并非所有),甚至同一个命名空间中的不同枚举类型的枚举值…...

第19章 MongoDB Limit与Skip方法教程
第19章 MongoDB Limit与Skip方法教程 MongoDB Limit() 方法 如果仁兄需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。 语法 limit()方法基本语法请…...

进程间通信——消息队列
多线程 进程间通信——消息队列 消息队列——发送 测试代码 #include <sys/types.h> #include <sys/msg.h> #include <sys/ipc.h>#include <stdlib.h> #include <stdio.h> #include <string.h>#define MAX_BUF_SIZE 255struct msgtype {…...

OpenMMLab 实战营打卡 - 第 7 课
OpenMMLab MMSegmentation内容概要MMSegmentation统一超参MMSegmentation 的项目结构分割模型的模块化设计分割模型的配置文件主干网络的配置ResNet v1c主解码头的配置辅助解码头的配置数据集配置数据处理流水线常用训练策略参考资料内容概要 • MMSegmentation 项目概述 • M…...

MAC Boook打印长图
有时老师给留的作业是一张长图,直接打印或者通过把图放入word打印都不能实现把长页分成多页进行打印。通过网上找到思路可以通过EXCEL实现将长图分成多页打印。 测试版本 macos:ventura 13.1 office 365 注:同样适用windows版本的excel 第…...

web3:区块链共识机制系列-POS(Proof of Stake)股权证明算法
web3相关学习一并收录至该博客:web3学习博客目录大全 前情衔接:web3:区块链常见的几大共识机制及优缺点 目录前言算法公式与原理算法公式运作原理以Peer Coin为例缺陷优点缺点特点分类发展历程casper协议1.什么是无成本利益关系问题2.引入casper协议解决…...

Linux fork()系统调用流程解析
1. fork()函数介绍(百度百科) fork系统调用用于创建一个新进程,称为子进程,它与进程(称为系统调用fork的进程)同时运行,此进程称为父进程。创建新的子进程后,两个进程将执行fork&…...

自定义软件帮助文档(qt assistant实现)
网上搜了一下,软件的帮助文档,三个都可以:https://github.com/zealdocs/zeal,https://zealdocs.org/,看看这个博客说的 https://blog.csdn.net/libaineu2004/article/details/125028913,这个也是开源的&…...

ESP32设备驱动-GPIO外部中断
GPIO外部中断 文章目录 GPIO外部中断1、GPIO中断介绍2、GPIO中断使用步骤3、软件准备4、硬件准备5、代码实现在前面的文章 ESP32设备驱动-GPIO数字输入与输出中介绍如何对GPIO进行控制操作。本文将在该基础上使用GPIO中断进一步优化按键输入。即演示如何使用GPIO中断。 1、GPI…...

【安全】nginx反向代理+负载均衡上传webshel
Nginx负载均衡下上传webshell 什么是反向代理? 正向代理就是代替客户端进行各种服务的访问以及获取;那么反向代理自然就是代替服务器进行事务处理,就是此时的代理服务器负责将用户的各项请求做一个汇总、分类,将其分发到不同的服务…...

华为OD机试 - 单词接龙(Python)| 真题,思路,知识点
单词接龙 题目 单词接龙的规则是: 可用于接龙的单词,首字母必须要与前一个单词的尾字母相同; 当存在多个首字母相同的单词时,取长度最长的单词; 如果长度也相等,则取字典序最小的单词; 已经参与接龙的单词不能重复使用; 现给定一组全部由小写字母组成的单词数组, 并指…...

[ 系统安全篇 ] window 命令禁用用户及解禁方法
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...

Https 协议超强讲解(二)
浏览器是如何确保 CA 证书的合法性? 1. 证书包含什么信息? 颁发机构信息 公钥 公司信息 域名 有效期 指纹 …… 2. 证书的合法性依据是什么? 首先,权威机构是要有认证的,不是随便一个机构都有资格颁发证书&am…...

C语言的程序环境和预处理详解
目录 一、程序的翻译环境和执行环境 二、编译和链接详解 2、1 翻译环境 2、2 编译过程详解 2、3 执行环境 三、预处理详解 3、1 预定义符号 3、2 #define 3、2、1 #define定义的符号 3、2、2 #define 定义宏 3、2、3 #define 替换规则 3、3 宏和函数的对比 3、4 条件编译 3、5…...

3.JUC【Java面试第三季】
3.JUC【Java面试第三季】前言推荐3.JUC06_闲聊AQS面试1.题目说明07_可重入锁理论2.可重入锁说明“可重入锁”这四个字分开来解释可重入锁的种类08_可重入锁的代码验证-上09_可重入锁的代码验证-下3.LockSupport10_LockSupport是什么LockSupport是什么11_waitNotify限制线程等待…...

Linux防火墙(7)
实验目的 通过该实验了解Linux防火墙iptables实现原理,掌握iptables基本使用方法,能够利用iptables对操作系统进行加固。预备知识基本原理 netfilter/iptables(简称为iptables)组成Linux平台下的包过滤防火墙,具有完成…...

2.11整理(2)(主要关于teacher forcing)
teacher forcing 训练迭代过程早期的RNN预测能力非常弱,几乎不能给出好的生成结果。如果某一个unit产生了垃圾结果,必然会影响后面一片unit的学习。RNN存在着两种训练模式(mode): free-running mode:就是常见的那种训练网络的方式: 上一个sta…...

亿级高并发电商项目-- 实战篇 --万达商城项目 三(通用模块、商品服务模块、后台API模块、IDEA忽略文件显示等开发工作
专栏:高并发项目 👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框…...

IDEA下java程序的调试(简易实例图示版)
在线排版不太好看,介意的读者可下载word下来看:https://download.csdn.net/download/xijinno1/87441301IDEA下java程序的简单调试-System.out.println首先本次进行调试的一个程序是实现从1累加到100的功能,是在IDEA下进行编写的。如图所示&am…...

动态规划算法
1.应用场景-背包问题 背包问题:有一个背包,容量为 4 磅 , 现有如下物品 要求达到的目标为装入的背包的总价值最大,并且重量不超出要求装入的物品不能重复 2.动态规划算法介绍 动态规划(Dynamic Programming)算法的核心思想是&…...

nacos的单机模式和集群模式
文章目录 目录 文章目录 前言 一、nacos数据库配置 二、单机模式 三、集群模式 四、使用nginx集群模式的负载均衡 总结 前言 一、nacos数据库配置 在数据库中创建nacos_config 编码格式utf8-mb4的数据库 把上面的数据库文件导入数据库 在 配置文件中添加如下 spring.datasour…...

Spring Boot 整合定时任务完成 从0 到1
Java 定时任务学习 定时任务概述 > 定时任务的应用场景非常广泛, 如果说 我们想要在某时某地去尝试的做某件事 就需要用到定时任务来通知我们 ,大家可以看下面例子 如果需要明天 早起,哪我们一般会去定一个闹钟去通知我们, 而在编程中 有许许多多的…...

Dialogue Transformers
Abstract 本文介绍了一种基于 Transformer 架构的 对话策略,其中自注意力机制被应用于对话轮次(dialogue turns)的序列上。近期的一些工作使用层次化的循环神经网络(hierarchical recurrent neural networks)在对话上下文中对多个话语(utterances)进行编码,但是我们认…...

【遇见青山】项目难点:缓存击穿问题解决方案
【遇见青山】项目难点:缓存击穿问题解决方案1.缓存击穿互斥锁🔒方案逻辑过期方案2.基于互斥锁方案的具体实现3.基于逻辑过期方案的具体实现1.缓存击穿 缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效…...

2023Flag具体实施计划(短期)
重新看了flag ,要做的事情太多,太杂,上周一周时间都在纠结和琢磨,该怎么下手。如何达成小目标。特别是沟通,汇报,演讲能力, 以及整体体系化的思维能力的训练。如何做到多思考,而不是瞎搞。这边重…...

研一寒假C++复习笔记--左值和右值的理解和使用
目录 1--左值和右值的定义 2--简单理解左值和右值的代码 3--非const引用只能接受左值 1--左值和右值的定义 左值:L-Value,L理解为 Location,表示可寻; 右值:R-Value,R理解为 Read,表示可读&a…...