进击的线段树——RMQ

前言

嗯,今天要讲的是进阶玄学, 有请玄学大师小Hi,小Ho登场

“唔……那我先从线段树的定义说起吧:线段树其实本质就是用一棵树来维护一段区间上和某个子区间相关的值——例如区间和、区间最大最小值一类的。”小Ho说道:“它的具体做法是这样的,这棵树的根节点表示了整段区间,根节点的左儿子节点表示了这段区间的前半部分,根节点的右儿子节点表示了这段区间的后半部分——并以此类推,对于这棵树的每个节点,如果这个节点所表示的区间的长度大于1,则令其左儿子节点表示这段区间的前半部分,令其右儿子表示这段区间的后半部分。以一段长度为10的区间为例,我所建立出的线段树应该是这样子的。”

“画的还凑合,但是这样一棵树有什么用呢?”小Hi明知故问道。
“就以RMQ问题为例吧——RMQ问题要求的是求解一段区间中的最小值,那么我不妨效仿ST算法,先对一些可能会用到的区间求解这个最小值!而既然我要是用线段树来解决这个问题的,那么我不妨就将每一个节点对应的区间中的最小值都求解出来。”小Ho道。
“那我给你这样一组数据,你将这个预处理的结果给我计算一下?”小Hi又出难题。

“好啊!你这数据正好也只有10个位置,那么我便直接用这棵树了。”只见小Ho刷刷两笔便在之前绘下的二叉树上写下了每个节点对应的区间中的最小值:“事实上这样一步相当好计算,由于每个非叶子节点所对应的区间都正好由它的两个儿子节点所对应的区间拼凑而成——那么只需要像ST那样,这样一个节点所对应的区间中的最小值便是它的两个儿子节点所对应的区间中的最小值中更小的那一个。这样我只需要O(N)的时间复杂度就可以计算出这棵树来。”

小Hi点了点头,继续问道:“我算是明白了,但是你这样一棵树统计出来的区间比ST算法统计出来的区间要少了很多,你还能够使用很快的算法进行查询么?更何况还有修改呢?”
小Ho笑了笑:“我先从简单的说起吧——修改,当某个位置的商品的重量发生改变的时候,对应的,就是这棵树的某个叶子节点的值发生了变化——但是和ST算法不同,包含这个节点的区间,便只有这个节点的所有祖先节点,而这样的节点数量事实上是很少的——只有O(log(N))级别。也就是说,当一次修改操作发生的时候,我只需要改变数量在O(log(N))级别的节点的值就可以完成操作了,修改的时间复杂度是O(log(N))。”
小Hi道:“是这样没错~算你过关!但是呢,还是像我之前所说的,你是准备如何使用数量在O(N)级别的区间来应付所有的询问呢?”
小Ho的笑容仍未退去:“这个其实也很简单!我要做的事情其实就是——将一个询问的区间拆成若干个我已经计算出来的区间(在ST算法中是拆成了2个的区间),这样对于这些区间已经计算出的最小值求最小值的话,我就可以知道询问的整个区间中的最小值是多少了!”
“那你准备如何分解询问的区间呢?”小Hi问道。
小Ho思索了一会,道:“这个问题其实很简单!我从线段树的根开始,对于当前访问的线段树节点t, 设其对应的区间为[A, B], 如果询问的区间[l, r]完全处于前半段或者后半段——即r <= (A + B)/2或者l > (A + B) / 2,那么递归进入t对应的子节点进行处理(因为另一棵子树中显然不会有任何区间需要用到)。否则的话,则把询问区间分成2部分[l, (A + B) / 2]和[(A + B) / 2 + 1, r],并且分别进入t的左右子树处理这两段询问区间(因为2棵子树中显然都有区间需要用到)!当然了,如果[A, B]正好覆盖了[l, r]的话,就可以直接返回之前计算的t这棵子树中的最小值了。还是之前那个例子,如果我要询问[3, 9]这段区间,我的最终结果会是这样的——橙色部分标注的区间。”

“首先[3, 9]分解成了[3, 5]和[6, 9]两个区间,而[3, 5]分解成了[3, 3]和[4, 5]——均没有必要继续分解,[6, 9]分解成了[6, 8]和[9, 9]——同样也没有必要继续分解了。每一步的分解都是必要的,所以这已经是最好的分解方法了。”
小Hi满意的点了点头,道:“听起来还不错?但是你这样分解的话,区间的个数你能保证么?万一很多怎么办?”
小Ho思索了一会,接着道:“不会的,除了第一次分解成2个区间的操作可能会将区间个数翻倍外,之后每一次分解的时候所处理的区间都肯定有一条边是和当前节点对应的重合的(即l=A或者r=B),也就是说即使再进行分解,分解出的两个区间中也一定会有一个区间是不需要再进行分解的,也就是区间的总数是在深度这个级别的,所以也是O(logN)的。”
“看来你还挺清楚的,那么要不你再总结一下,我就算你过关,然后我们就可以开始讲解后面的问题了~”
小Ho道:“好的!首先我会根据初始数据,使用O(N)的时间构建一棵最原始的线段树,这个过程中我会使用子节点的值来计算父亲节点的值,从而避免冗余计算。然后对于每一次操作,如果是一次修改的话,我就将修改的节点和这个节点的所有祖先节点的值都进行更新,可以用O(logN)的时间复杂度完成。而如果是一次询问的话,我会使用上面描述的方法来对询问区间进行分解,这样虽然不像ST算法那样是O(1),但是却实现了上一次所提到的‘平衡’,无论是修改还是查询的时间复杂度都是O(logN)的,所以我这个算法最终的时间复杂度会是O(N + Q * log(N)),在这个数据规模下是绰绰有余的!”
“嗯~ o( ̄▽ ̄)o 不错哟~那么就到这里吧!”小Hi笑容满满道:“赶紧去吃早饭吧!”

算法

看完HiHO大师的讲解,相信大家都已经懂了一点了吧。那么,蒟蒻不才,要接着上面的博客开始讲解了。
(上一篇:基本线段树
首先,我们在结构体中加入”minn”变量,用来存储线段中的最小值。
每一次插入线段后,都要更新minn的值。

tree[number].minn=min(tree[number2].minn,tree[number2+1].minn) t r e e [ n u m b e r ] . m i n n = m i n ( t r e e [ n u m b e r ∗ 2 ] . m i n n , t r e e [ n u m b e r ∗ 2 + 1 ] . m i n n )

就这么简单,完啦。

实现

这些是RMQ的读入+传值部分代码

void Insert(int i,int ad,int val){
    if(tree[i].l>ad||tree[i].r<ad) return;
    if(tree[i].l==tree[i].r){
        tree[i].minn=val;
        return;
    }
    Insert(i*2,ad,val);
    Insert(i*2+1,ad,val);
    tree[i].minn=min(tree[i*2].minn,tree[i*2+1].minn);
}

这里是RMQ的核心查找部分代码

int Find(int i,int l,int r){
    if(r<tree[i].l||l>tree[i].r)//如果线段不能配对(这里用的方法2)
        return 10000000;
    if(l<=tree[i].l&&tree[i].r<=r)//如果这个是匹配线段
        return tree[i].minn;
    return min(Find(2*i,l,r),Find(2*i+1,l,r));//如果这条线段包含目标线段
}
基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究”展开,提出了一种结合数据驱动方法与Koopman算子理论的递归神经网络(RNN)模型线性化方法,旨在提升纳米定位系统的预测控制精度与动态响应能力。研究通过构建数据驱动的线性化模型,克服了传统非线性系统建模复杂、计算开销大的问题,并在Matlab平台上实现了完整的算法仿真与验证,展示了该方法在高精度定位控制中的有效性与实用性。; 适合人群:具备一定自动化、控制理论或机器学习背景的科研人员与工程技术人员,尤其是从事精密定位、智能控制、非线性系统建模与预测控制相关领域的研究生与研究人员。; 使用场景及目标:①应用于纳米级精密定位系统(如原子力显微镜、半导体制造设备)中的高性能预测控制;②为复杂非线性系统的数据驱动建模与线性化提供新思路;③结合深度学习与经典控制理论,推动智能控制算法的实际落地。; 阅读建议:建议读者结合Matlab代码实现部分,深入理解Koopman算子与RNN结合的建模范式,重点关注数据预处理、模型训练与控制系统集成等关键环节,并可通过替换实际系统数据进行迁移验证,以掌握该方法的核心思想与工程应用技巧。
基于粒子群算法优化Kmeans聚类的居民用电行为分析研究(Matlb代码实现)内容概要:本文围绕基于粒子群算法(PSO)优化Kmeans聚类的居民用电行为分析展开研究,提出了一种结合智能优化算法与传统聚类方法的技术路径。通过使用粒子群算法优化Kmeans聚类的初始聚类中心,有效克服了传统Kmeans算法易陷入局部最优、对初始值敏感的问题,提升了聚类的稳定性和准确性。研究利用Matlab实现了该算法,并应用于居民用电数据的行为模式识别与分类,有助于精细化电力需求管理、用户画像构建及个性化用电服务设计。文档还提及相关应用场景如负荷预测、电力系统优化等,并提供了配套代码资源。; 适合人群:具备一定Matlab编程基础,从事电力系统、智能优化算法、数据分析等相关领域的研究人员或工程技术人员,尤其适合研究生及科研人员。; 使用场景及目标:①用于居民用电行为的高效聚类分析,挖掘典型用电模式;②提升Kmeans聚类算法的性能,避免局部最优问题;③为电力公司开展需求响应、负荷预测和用户分群管理提供技术支持;④作为智能优化算法与机器学习结合应用的教学与科研案例。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,深入理解PSO优化Kmeans的核心机制,关注参数设置对聚类效果的影响,并尝试将其应用于其他相似的数据聚类问题中,以加深理解和拓展应用能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值