树状数组

为了完成 计算右侧小于当前元素的个数,我们需要先了解一个全新的数据结构——树状数组。

考虑以下需求,对于一个数组,我们需要两个方法:

我们容易想到下列两种解决方案

不管是上述解决方案中的哪种,在面对 n 次随机操作时,其期望的时间复杂度都是 O(n2),可以说是无法适应大数据量的。

那有没有什么办法可以将这两种操作的时间复杂度都变得很低呢?这就要使用树状数组了。

我们先来了解一个前置知识,什么是 lowbit。

lowbit 定义为非负整数 n 在二进制表示下最低位的 1 及其后面的所有的 0 的二进制构成的数值。

例如:

数字二进制表示lowbit
100011
2001010
300111
40100100
501011

为了快速求得数字 n 的 lowbit 值,我们可以使用 n ^ ~n + 1。也即 n 取反加一,再和原 n 的值按位与。由于计算机里负数用的是补码表示负数,那么我们直接用 n ^ -n 即可求出 lowbit(n)

下面来正式介绍树状数组(图片来自视频

如图所示,这就是一个树状数组结构。

在这种情况下,add()ask() 方法都惊人地达到了 O(logn) 的时间复杂度,非常高效,这表明树状数组非常时候需要动态改变前缀和的情况。

下面给出代码:

结合上面的图片,我们来理解一下为什么代码是这样的

树状数组的应用:

赣ICP备20003470号-4