- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
第10章 线段树和树状数组
∮10.1 从一个实例入手
引例 线段覆盖问题
有一根长度为L的白色条状物。有两种操作:
用一条长度为T的黑布盖住条状物的[a, a+T]这个区间(0=a, T=L)。
把某条黑布拿走。
输入L和n次操作,要你输出每次操作之后:
条状物上有多少个黑区间。
条状物上黑区间的总长度。
分析1—线性表
见上图示,我们可以用一个数组来保存木板的状态。
Count : array[0 .. L+1] of Integer;
一开始Count数组的所有元素置0。
如果要添加一根布条(a, T),那么:
for i ( a to a+T-1 do
Count[i](Count[i]+1
如果要撤掉一根布条(a, T),那么:
for i ( a to a+T-1 do
Count[i](Count[i]-1
每次要输有多少个黑色区间可以这样做:
Count[L+1](0
Interval(0
for i(1 to L do
if (Count[i]0) and (Count[i+1]==0) then Interval ( Interval+1
Writeln(Interval)
每次要输出黑色区间的总长度:
Sum(0
for i(0 to L-1
if Count[i]0 then Sum(Sum+1
Writeln(Sum)
这种直观的做法是对白色条状物被黑布覆盖情况的忠实模拟。虽然编程复杂度和思维复杂度都很低,但是时间复杂度过高——O(nL)。当n和L达到100000的规模是,算法就无能为力了。下面我们来看另一种思路。
分析2—线段树
整个条状物可以看作是一条长度为L的线段。建立一棵树:
根节点是[0,L],代表整条线段。然后从根节点开始,递归的将每个节点分成尽量等长的两段,作为左右子树;直到节点变成[a,a+1]的形式为止。
这显然是一颗平衡树,深度为O(Log2L),节点总数为O(n)(也就是说空间复杂度为O(n),建树的复杂度也是O(n))。
对于任意一条线段,我们都可以将其分解成为树中一些线段来表示:
设根节点是Root,节点X的左孩子是LChild(x)、右孩子是RChild(x),节点X代表的线段区间是[L(x)..R(x)]。那么添加一条黑布[a,b]可以这么进行:
procedure Add(Root, a, b);
begin
if Root = NIL then
Exit;
if (a=L(Root))and(b=R(Root)) then {[a,b]完全包含该线段}
Count[Root] ( Count[Root] + 1 {因为Root代表的线段被覆盖了,所以将其标记}
else if (b=L(Root)or(a=R(Root)) then {[a,b]和该线段不相交}
Exit {不执行任何操作}
else {[a,b]和Root代表的线段有交集,但是却不完全包含}
begin
Add(LChild(Root), a, b);
Add(RChild(Root), a, b);
end;
end;
撤掉一条黑布可以类似的操作,只要把Count[Root](Count[Rotot]+1改成Count[Root](Count[Root]-1即可。
那么上面过程的时间复杂度是多少呢?
我们用f(Root)表示执行Add(Root, a, b)的时间复杂度。下面我们证明f(Root)~O(Log2n)。
如果(a=L(Root))and(b=R(Root)),也就是说[a,b]完全包含了Root代表的线段,那么f(Root)=1。
否则如果(b=L(Root)or(a=R(Root)),也就是说[a,b]和Root代表的线段完全没有交集,那么f(Root)=1。
如果以上两项都不满足,那么[a,b]和Root代表的线段有交集,并且不是完全包含。假设[a,b]和Root的交集是[x,y]。
令m=(L(Root)+R(Root))/2,也就是说LChild(Root)代表的线段是[L(Root)..m],RChild(Root)代表的线段是[m..R(Root)]。
首先我们归纳证明,当x=LChild(Root)或者y=RChild(Root)时,f(Root)=Log2n成立。(这个我们称之为引理)其中n=R(Root)-L(Root),我们对n进行归纳。
f(Root)=f(LChild(Root))+f(RChild(Root))
1.如果x=L(Root)
如果y=m,那么f(RChild(Root))=0,所以f(Root)=f(LChild(Root))。根据归纳假设f(LChild(Root))=Log2n
您可能关注的文档
最近下载
- 2025-2026人教部编版三年级上册语文教学计划.docx VIP
- 施工现场车辆安全教育.pptx VIP
- 给排水系统学习培训ppt课件.pptx VIP
- 2025北京市十八里店乡人民政府城市协管员招聘21人笔试参考题库附答案解析.docx VIP
- 输血科管理制度、程序性文件、SOP文件.docx VIP
- 05J909_工程做法_建筑专业图集.docx VIP
- 2021海绵城市设施通用图集.docx VIP
- 【统编版】高中语文必修上册第一单元《3百合花》优质课(29张PPT)课件.pptx VIP
- 钢丝帘线压延机生产线(中文参考).doc VIP
- 2025年福建省福州市辅警协警笔试笔试预测试题(含答案).docx VIP
文档评论(0)