重学树状数组

树状数组

\(def\) :树状数组(Binary Indexed Tree) 用于维护数列的前缀和的数据结构,区间和.在\(\log n\) 的复杂度得到任意前缀和\(\sum_{i=1}^{i} A[i] , i <= j <= n\) 或动态修改单点值.其中维护信息需保证可差分,结合律.

\(first\) : 我们定义\(lowbit(x)\) 运算表示取 \(x\) 二进制下的最小1所代表的数即\(2^k\).我们可以通过\(O(1)\) 的复杂度进行\(x\&-x\)位运算来得到.

BIT 的基本运算便是基于 \(lowbit\) 实现的,通过\(lowbit\) 运算将我们要求的前缀和进行拆分为不多于\(\log n\) 块,我们通过合并这\(\log n\) 块区间便可以得到我们所求的信息.
\(def_1\): \(BIT_i = \sum_{j=i-lowbit(i) + 1}^i Aj\)
\(def_2\): \(l(x) = x - lowbit(x) + 1\)\(l(x)\)\(A[x]\) 管辖的左端点.

区间求值修改

对于一个数列\(A\) 我们定义其前缀\(S\)和与差分\(C\)
\(def_1\) :前缀和 \(s_n=\sum_{i=1}^na_i\)
\(def_2\) :差分

\[\begin{cases} & c_i = a_i - a_{i-1} \ \ i \not = 1 \\ & \text {else} \ \ c_i = a_i \end{cases} \]

通过观察上式很容易可以看出\(a_n = \sum_{i=1}^nc_i\)

\[\begin{array}{l} d_n = \sum_{i = 1}^{n} a_i \\ d_n = \sum_{i = 1}^{n}\sum_{i = 1}^{n}c_i\\ d_n = \sum_{i}^{n}(n - i + 1)c_i \end{array} \]

进入正题
对于查询\(\sum_{1}^{n} a_i\)

\[\begin{array}{l} \ \ \sum_{i = 1}^{n} a \\ = \sum_{i = 1}^{n} \sum_{j = 1}^{i}d_j \\ \end{array} \]

对于 \(d_1\) 显然被加了 \(n\) 次,\(d_2\) 被加了 \(n - 1\) 次。数学归纳,每个 \(d_j\) 被加了\(n - j + 1\)

\[\begin{array}{l} \ \ \sum_{i = 1}^{n} \sum_{j = 1}^{i}d_j \\ = \sum_{i = 1}^{n} d_i \times (n - i + 1) \\ = \sum_{i = 1}^{n}d_i \times (n + 1) - \sum_{i = 1} ^{n}d_i \times i \end{array} \]

我们无法通过\(\sum_{i = 1}^{n}d_i\) 得到 \(\sum_{i = 1}^{n}d_i \times i\),所以需要分别维护\(d_i\)\(d_i \times i\) 的和的信息
对于\(add(l,r,x)\)\(\sum_{l}^{r} a_i +x\)操作 ,根据差分性质操作,空间复杂度为\(O(n)\) 时间复杂度为\(\log(n)\)

对于以上BIT的建树方法可以通过插入方式\(O(n\log n)\) 的复杂度进行建树,也可以通过\(O(n)\) 的复杂度进行建树由于每个父节点为子节点之和我们可以通过定义反推建树.

posted @ 2023-10-12 16:57  Erfu  阅读(25)  评论(0编辑  收藏  举报