- 1、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
《线段树》讲稿
《线段树》讲稿
else
modify(v的右儿子,i,newvalue)
end if
v区间的最小值 - min(w区间的最小值,x区间的最小值) //更新数据
end function
由于每个节点都至多递归一次, = O(树深度) = O(log n)。
区间查询操作
继续上面的例子,由于RMQ的目的是在区间内查询最小值,现在讨论如何利用刚刚构造出来的线段树高效回答这一提问:
比如刚才图中所示的树,如果询问区间是[0,2],或者询问的区间是[3,3],不难直接找到对应的节点回答这一问题。但并不是所有的提问都这么容易回答,比如[0,3],就没有哪一个节点记录了这个区间的最小值。当然,解决方法也不难找到:把[0,2]和[3,3]两个区间(它们在整数意义上是相连的两个区间)的最小值“合并”起来,也就是求这两个最小值的最小值,就能求出[0,3]范围的最小值。同理,对于其他询问的区间,也都可以找到若干个相连的区间,合并后可以得到询问的区间。
幸运的是,很容易证明对于任何询问,这样的区间的个数不会超过O(log N)个。通常用来寻找这样一个区间的简单办法是,从根节点开始执行以下步骤:
function 在节点v查询区间[l,r]
if v所表示的区间和[l,r]交集不为空集
if v所表示的区间完全属于[l,r]
选取v
else
在节点v的左右儿子分别查询区间[l,r]
end if
end if
end function
首先可见,这样的过程一定选出了尽量少的区间,它们相连后正好涵盖了整个[l,r],没有重复也没有遗漏。同时,考虑到线段树上每层的节点最多会被选取2个,一共选取的节点数也是O(log n)的。类似地,同一层被访问的节点不会超过4个,因此查询的时间复杂度也是O(log n)。
换个问题,比如说我们的问题是:
对于一个长度为N的数字串S(从S[0]到S[N-1]),定义
/ S[(N - 1) / 2] 如果N是奇数
f(S) = {
\ f(S[0]..S[N / 2 - 1]) + f(S[N / 2]..S[N - 1]) 如果N是偶数
给定数字串,要求能够回答它的某些子串的f值。
在N是2的整数次幂时,很容易按照题目条件构造出这棵线段树。对于修改某一个数字这样的操作,也是非常容易的。但是问题来了,真当我们想去用这棵线段树来回答题目中的提问,才会发现,我们选出了O(log n)个线段,它们相连,正好涵盖了我们所询问的区间。而且这些线段的f值都是已知的。可惜的是,这些信息对回答询问毫无帮助。
那么,什么情况下,线段树可以发挥它应有的功能,回答我们的区间查询呢?
当相邻的区间的信息,可以被合并成两个区间的并区间的信息时,就可以回答区间查询。
第一例中,两个相邻区间的最小值中的较小值,就是并区间的最小值。
第二例中,同等长度的数字串的f函数可以合并,但是不同长度就不可以。因此,虽然可以构造出这棵线段树,却不能回答我们所期望回答的区间询问。
区间修改操作
仍然以RMQ问题为例,如果现在的修改操作一次可以修改的范围也是一个区间,比如给一个区间内所有数同时加上或减去某数,如果按照前面的定义,改动的节点数必定会远远超过O(log n)个。
原因是,我们这样的操作并没有很好利用修改操作也是对一个区间进行操作的性质。
既然要想把区间修改操作也控制在O(log n)的时间内,只修改O(log n)个节点的信息就成为必要。直观上,我们可以直接用前面给出的方法把操作区间变成O(log n)个相连的节点所表示的小区间。对每个区间进行一次修改操作,即可覆盖整个操作区间。正如查询操作如果查询的就是一个节点所表示的区间,就不用查找它的儿子节点的信息,区间修改时如果修改了一个节点所表示的区间,也不用去修改它的儿子节点。然而,对于被修改节点的祖先节点,也必须更新它所记录的值,否则查询操作就肯定会出问题(正如修改单个节点的情况一样)。
这些选出的节点的祖先节点直接更新值即可,而选出的节点却显然不能这么简单地处理:每个节点的值必须能由两个儿子节点的值得到,如这幅图中的例子:
这里,节点[0,1]的值应该是4,但是两个儿子的值又分别是3和5。如果查询[0,0]区间的RMQ,算出来的结果会是3,而正确答案显然是4。
问题显然在于,尽管修改了一个节点以后,不用修改它的儿子节点,但是它的儿子节点的信息事实上已经被改变了。这就需要我们在节点里增设一个域:标记。把对节点的修改情况储存在标记里面,这样,当我们自上而下地访问某节点时,就能
您可能关注的文档
最近下载
- 西门子S7-200 SMART PLC应用技术图解项目教程全册教案.docx VIP
- 《GB_T 14894 - 2005城市轨道交通车辆组装后的检查与试验规则》必威体育精装版解读.docx VIP
- 云南省药品经营质量管理标准规范现场检查评定统一标准.doc VIP
- 校园智能零售合作计划:自动售货机服务方案探索.docx VIP
- 对电磁线用铜杆的要求-漆包线.PDF VIP
- 快递站客服外包合同.docx VIP
- 从历史文物看丝绸之路刘兴隆培训讲学.doc VIP
- 胃肠减压技术的操作流程及评分标准.doc VIP
- TNAHIEM 142—2025《医院可复用手术器械管理规范》.pdf
- 2021年大学内部审计工作总结.doc VIP
文档评论(0)