网站大量收购独家精品文档,联系QQ:2885784924

树状数组方法总汇.doc

  1. 1、本文档共9页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
树状数组简介 一、前言 我们平日里总是会遇到一些动态的求和问题,一些朴素的方法时间速度上很难让人满意,因此我们需要设计一些算法来解决所遇到的问题。 基本问题 我们下面设法解决这个动态求和问题。 我们定义 N 个整型变量组成的数组 v[1..N],每次操作有两种: 将v[idx] 增加 det 求 朴素解决 朴素的解决这个问题,我们用数组记录当前的数值,然后依次求和。那么操作(1)的复杂度是 O(1),操作(2)的复杂度是 O(idx),令询问数为 Q ,则在最坏情况下为 O(QN)。 这样的复杂度非常不理想,我们要对之优化! 二、倍增,分割和优化 很多时候在处理区间问题的时候,倍增思想都是非常常用的,比如 RMQ和LCA问题,而分割方法也是一个有用的工具,比如线段树。 我们知道线段树是能够解决上面这个基本问题的,但是考虑到线段树的代码比较复杂,这里我们讨论更轻松的方法。 第一个想法 我们发现,在朴素算法中,操作(2)用了很多的时间,我们试着优化这个操作的算法。 参照RMQ的思想,我们可以将一个区间分成一些长度为2的整次幂的小区间。 我们定义f[i][j] 表示区间 [I, i+2^j-1] 的和,那么如果我们能够得到所有 f[i][j] ,那么我们就能够在 O(log N) 的时间里计算出我们需要的和。 具体方法如下: 对于区间 [L,R],我们找到最大的 p ,使得 2^p = R-L+1,而 sum[L,L+2^p-1] = f[L][p],于是我们只要继续计算 [L+2^p,R]就可以了。 由于每次找最大的 p,因次至多计算 log N 次就能得到结果——这就是倍增思想的应用。 但是很不幸,我们再观察操作(1)的时候,我们发现由于和某一个位置相关的 f[i][j] 实在太多了,所以操作(1)的时间就花的过多了,问题并没有得到解决。 看来我们并不能完全照搬 RMQ 问题的经验——RMQ是静态问题,而这里是动态的。 化简问题 我们回过头看我们研究的问题,我们只需要求 [1,idx] 的和,并不需要求出任意区间的和,所以我们保存了大量没用的 f[i][j] ,因此使得我们操作(1)所需要的时间过多。 现在我们要删去我们不需要的 f[i][j],让数据变得更加紧凑。 观察计算区间 [1,R],我们找到最大的 p,满足 2^p = R,我们用到的f[1][p],之后我们会紧接着计算 [2^p+1,R],似乎我们跳过了所有的 f[i][p] (1i2^p+1),那么所有这样的 f[i][p] 是否会用到呢? 答案是否定的。简单证明一下: 反证法:假设计算区间为 [1..R],上次使用的为f[j][q],当前区间为 [2^q+1,R],计算得到最大的p满足 2^p + 2^q = R ,且有 2^q +1 2^p + 1。则 2^p 2^q,2^q = R,因此上次得到的 q,必然不是最大 q,使得 2^q = R,p 比 q 更优。假设不成立。(证毕) 接着我们不难归纳得出,我们只可能用到 f[i][p] (i mod 2^p = 1)。如下图。 方块就表示一个对应的 f[i][p] ,即一段部分和。 可以发现,现在,对于一个下标 idx ,eter M. Fenwick首先提出的。BIT在快速求和方面有常数小、速度快、空间需求低、代码简洁等许多优点,很短时间便广泛流传。 从英文来看,不难看出,BIT是一个tree,其实设计它的时候本身就是用树的理念设计的。我们如果加一个结点0为根,元素对应的覆盖区域若相邻便连边,很容易建立出这么一颗有根树。 这个树的意义在于:对于区间和 [1,R],只要取出0-R的这条路径 ,interrogation tree)。 而这棵树的深度是 Log N 级别的,宽度也是 Log N 级别的。 其实还有一种更新树(The updating tree),和询问树对应,我们这里暂且不讲,本文稍后会提到。树状数组正是基于这两颗树而工作的。 而这Binary Indexed Tree为什么翻译后就成了“数组”,原因不详,据笔者理解应该是BIT在实现过程中多用数组,而且操作简便,于是其树的形式便被渐渐遗忘了吧。 技术实现 下面我们要讨论如何在BIT这个Tree上“行走”。 对应关系 我们利用数组 t记录对应的部分和。L(i)表示t[i]对应的那个块的长度。下面需要解决的就是如何快速的计算出L(i)。 我们写一张表来研究这个问题。 I 1 2 3 4 5 6 7 8 9 10 11 I的2进制数写 1 10 11 100 101 110 111 1000 1001 1010 1011 L(I) 1 2 1 4 1 2 1 8 1 2 1 L(I)的2进制书写 1 10

文档评论(0)

希望之星 + 关注
实名认证
内容提供者

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

1亿VIP精品文档

相关文档