当前位置: 首页 > news >正文

树状数组的原理和简单实现:一种使用倍增优化并支持在线 O(log N) 修改、查询的数据结构

一、概述

考虑这样一种问题:

现有一个由 NNN 个整数组成的数列 AAA,满足 ∀1≤i≤n,ai∈[−109,109]\forall 1 \le i \le n, \space a_i \in [-10^9, 10^9]∀1in, ai[109,109]
接下来你要进行 QQQ 次操作,单次操作有两种类型:

  • 1lrx1 \space l \space r \space x1 l r x ,表示 ∀i∈[l,r],ai←ai+x\forall i \in [l,r], a_i \leftarrow a_i+xi[l,r],aiai+x
  • 2lr2 \space l \space r2 l r ,你应该输出 ∑i=lrai\displaystyle\sum_{i=l}^{r}{a_i}i=lrai

对于每个 222 类操作,输出其答案。

如果使用暴力算法求解,则直接进行操作,复杂度为 O(N2)O(N^2)O(N2) 。如果我们可以使用树状数组(Fenwick Tree)求解,则时间复杂度可以降低至 O(Nlog⁡N)O(N \log N)O(NlogN)

二、 lowbit 函数的定义和原理

1. 定义

lowbit(x)\mathrm{\bold{lowbit}}(x)lowbit(x) 函数是指由一个数 xxx 在二进制下最后一个 111 以及后面的 000 组成的数。例如, lowbit(24)=8,lowbit(16)=16\mathrm{lowbit}(24)=8, \space \mathrm{lowbit}(16)=16lowbit(24)=8, lowbit(16)=16

2. 性质及求法

使用 lowbit\mathrm{lowbit}lowbit 函数可以遍历二进制下一个整数 xxx 的每一个 111 。例如,我们对 15=(1111)215=(1111)_215=(1111)2 进行操作,每一次减少它的 lowbit\mathrm{lowbit}lowbit ,则它的变化如下:
15→14→12→8→015 \rightarrow 14 \rightarrow 12 \rightarrow 8 \rightarrow 0 15141280
C++代码如下:

inline void lowbit(int x)
{for (int i = x; i; i -= lowbit(i)) // lowbit(i) 的实现将在后面介绍{// do something}
}

下面介绍 lowbit\mathrm{lowbit}lowbit 函数的求法。
我们可以运用计算机二进制补码的性质,补码即反码加上一,由于反码的每一位都和原码不同,故补码中的最后一个 111 与原码中的最后一个 111 重合。因此, 补码 & 原码 的操作就可以实现求 lowbit ,时间复杂度为 O(1)O(1)O(1)
实现方法如下:

#define lowbit(x) x & (-x)     // -x    : x 的补码
#define lowbit(x) x & (~x + 1) // ~x + 1: x 的反码加一(补码)

例如:二进制下 141414lowbit\mathrm{lowbit}lowbit 求法:
14=(1110)2−14=(111⋯0010)2⇒14&(−14)=(10)2=2\begin{align*} 14&=(1110)_2 \\ -14&=(111 \cdots 0010)_2 \\ \Rightarrow 14\space \&\space (-14) &= (10)_2=2 \end{align*} 141414 & (14)=(1110)2=(1110010)2=(10)2=2
经验证,结果正确。

3. 应用

因为二进制的 lowbit\mathrm{lowbit}lowbit 函数具有较强的位处理特性,所以常被用来处理与二进制有关的问题,例如在状态压缩 DP 中, lowbit\mathrm{lowbit}lowbit 函数可以减少不必要的计算,直接提取每一个有效位数,减少时间复杂度; lowbit\mathrm{lowbit}lowbit 函数还可以用来解决一些倍增问题,将问题的时间复杂度从 ≥O(n)\ge O(n)O(n) 量级优化为 O(log⁡n)O(\log n)O(logn) 量级。

接下来, lowbit\mathrm{lowbit}lowbit 函数将会被广泛地使用于树状数组中,解决各类问题。

三、树状数组的单点修改和区间查询

1. 树状数组的实现原理

树状数组既不是树,也不是数组,是一种特殊的数据结构。树状数组的一个节点 cxc_xcx 保存序列 AAA 的区间 [x−lowbit(x)+1,x][x - \mathrm{lowbit}(x)+1,x][xlowbit(x)+1,x] 内所有元素的总和,即 cx=∑i=x−lowbit(x)+1xaic_x= \displaystyle\sum_{i=x - \mathrm{lowbit}(x)+1}^{x}{a_i}cx=i=xlowbit(x)+1xai 。通过一次保存一个 lowbit\mathrm{lowbit}lowbit 之内所有的数值,我们可以实现缩小查找需要的时间。树状数组的示例图如下:
在这里插入图片描述
若记一个节点 xxx 的子节点的集合为 s(x)s(x)s(x) ,树状数组满足以下几个性质:

  1. cx=∑y∈s(x)yc_x=\displaystyle\sum_{y \in s(x)}{y}cx=ys(x)y
  2. ∣s(x)∣=log⁡2lowbit(x)|s(x)|=\log_2\mathrm{lowbit}(x)s(x)=log2lowbit(x)
  3. cxc_xcx 的父节点是 cx+lowbit(x)c_{x+\mathrm{lowbit}(x)}cx+lowbit(x)
  4. 树的深度 ≤O(log⁡n)\le O(\log n)O(logn)

2. 树状数组的插入操作

要给一个数增加一个特定的值,则这个数的位置之后的前缀和也会相应的增加这个值。根据这个原理以及树状数组的性质 2,3,我们可以使用 lowbit\mathrm{lowbit}lowbit 函数定义树状数组的插入操作:

inline void add(int x, int v)
{for (; x <= N; x += lowbit(x))tr[x] += v;
}

3. 树状数组的求和操作

由树状数组的性质 1,知要求 ∑i=1nai\displaystyle\sum_{i=1}^{n}a_ii=1nai 的时候,只需要遍历每一个 lowbit(n)\mathrm{lowbit}(n)lowbit(n) 即可。

inline int query(int x)
{int res = 0;for (; x; x -= lowbit(x))res += tr[x];return res;
}

4. 完整代码实现

#define lowbit(x) x & (-x)
template <class _Tp>
class FenwickTree
{
private:int tr[N];public:inline void add(int x, _Tp v){for (; x <= N; x += lowbit(x))tr[x] += v;}inline _Tp query(int x){_Tp res = 0;for (; x; x -= lowbit(x))res += tr[x];return res;}
}

参考文献:

  1. 《算法竞赛进阶指南》0x42 树状数组,李煜东
  2. OI Wiki 网站树状数组部分
http://www.dtcms.com/a/431985.html

相关文章:

  • 网站相关知识百度如何收录网站
  • 视频素材网站大全免费海盐市网站建设
  • 一个公司名可以备案多少个网站空间设计主要做什么
  • STC32G 的PWM调光LED
  • wordpress 建网站 vpn校网站建设方案
  • MySQL索引全面解析:类型作用与最佳实践
  • 护理+人工智能研究热点数据分析项目实战(六)
  • JVM参数及问题排查工具
  • 全部网站网站开发需要哪些基础技术
  • (基于江协科技)51单片机入门:9.蜂鸣器
  • 服装网站建设报关微信公众号平台网站开发
  • 旧金山网站建设互联网公司加盟
  • Pod 介绍
  • 全国商城网站建设石大网页设计与网站建设客观题
  • 广西钦州有人帮做网站的公司吗wordpress必须安装php吗
  • 深入解析Kerberos协议攻击手法:从基础到高级攻防实战
  • 现在网站建站的主流语言是什么东莞品牌网站建设费用
  • NO.10数据结构图|Prim算法|Kruskal算法|Dijkstra算法|Floyd算法|拓扑排序|关键路径
  • 深圳市西特塔网站建设工作室wordpress 本地访问慢
  • 网站制作的发展趋势网站文件目录
  • 旅游公网站如何做室内设计效果图怎么画
  • Acrobat DC 文本域表单验证中的 js 使用
  • 商务网站开发代码h网站建设
  • 动态规划完整入门
  • 网站怎么做端口映射想访问国外网站 dns
  • 【Linux系列】并发世界的基石:透彻理解 Linux 进程 —— 从调度到通信的深度实践
  • 专业设计网站排名网站建设忄金手指快速
  • 怎么申请自己的网站网址网站建设响应
  • 西部数码网站管理助手serv-u默认密码杭州seo网站推广排名
  • 好的网站具备什么条件网站运营建设方案