线段树和树状数组资料.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 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

文档评论(0)

希望之星 + 关注
实名认证
文档贡献者

我是一名原创力文库的爱好者!从事自由职业!

1亿VIP精品文档

相关文档