【数据结构与算法】树状数组

news2024/9/20 9:10:21

Fenwick Tree


树状数组(Binary Indexed Tree,又称 Fenwick Tree)是一种基于数组实现的数据结构,用于高效地动态维护前缀和。

树状数组可以在 O ( log ⁡ n ) O(\log n) O(logn) 的时间复杂度内进行单点修改前缀求和操作,适用于一些仅需要维护前缀和的问题,例如区间求和、区间平均数、区间中位数等。

一、问题描述

对于给定数组 a 1 , a 2 , . . . , a [ n ] a_{1},a_{2},...,a[n] a1,a2,...,a[n],当需要频繁询问某一区间 a i , a i + 1 , . . . , a [ j ] a_{i},a_{i+1},...,a[j] ai,ai+1,...,a[j] (其中 1 < = i < j < = n 1<=i<j<=n 1<=i<j<=n),且存在修改 a i a_{i} ai 元素值的情况时,如何设计一种高效的查询和修改算法?

一种直观的做法是暴力法,即每次使用 O ( 1 ) O(1) O(1) 的时间复杂度进行单点修改,但是查询的过程中由于需要遍历区间中的每个元素,最坏情况需要 O ( n 2 ) O(n^{2}) O(n2) 的时间(这里是假设操作的规模是 O ( n ) O(n) O(n) )。为了解决这种查询效率低下的情况,一种思路是使用树状数组。

二、解决思想

在树状数组 d d d 中,每个数组位置所存储的值并不仅仅是当前元素的值,而是一定区间内元素的累加值,具体存储规则如下图左图示所示。

在这里插入图片描述

左图示中,元素下标对应的矩阵表示该位置存储的值为矩阵覆盖区域对应的原数组元素之和,比如下标为 1 1 1 处存储原数组下标为1的元素值,下标为4处存储原数组下标为 1 1 1 4 4 4 的元素值之和。

树状数组的存储图中反映的存储规律为:

编号为 x x x 的节点所管辖的区间为 2 k 2^{k} 2k(其中 k k k x x x 二进制末尾 0 的个数)个元素。

比如 d [ 6 ] = a [ 5 ] + a [ 6 ] d[6] = a[5] + a[6] d[6]=a[5]+a[6],因为位置 6 对应的二进制为 110,末尾的 0 个数为 1,因此需要存储 2 1 = 2 2^{1} = 2 21=2 个元素,其他同理。

有了上述的存储规则后,如何进行区间查询和元素修改操作呢?为了便于对操作的描述,可将左侧图示进行旋转获得右侧图示(树的深度为 l o g 2 n + 1 log_{2}{n+1} log2n+1),并用直线连接表示前缀累加节点之间的关联关系。另外,为了便于后续对区间查询和元素修改操作的描述,这里引入 lowbit 操作:

public int lowbit(int x) {
    return x & (-x);
}

即所谓的 lowbit 操作就是为了获取当前变量 x x x 二进制中最后一个 1 的位置。这个操作可以先记住,后续的操作介绍中能帮助进一步理解。

(1)区间查询

在右侧图示的树结构中,若查询某个节点的前缀和,则需要从这个点向左上找到上一个节点,并加上其节点的值,以此不断向左上查找节点值并累加。比如,查询 节点 7 的前缀和,需要从 节点7 出发, 找到 节点 6 进行累加操作,再找到 节点 4 进行累加操作(可以结合图中矩阵的覆盖面积进行理解)。那么这一遍历过程是如何实现的呢?这需要我们先将节点编号转成二进制的形式:

  • 7 ---- 0111
  • 6 ---- 0110
  • 4 ---- 0100

可以发现一个普遍的规律:下一次遍历的位置 x ′ x' x 是当前位置 x x x 在二进制位上抹去最后一个 1 1 1。因此,这时就可以使用到我们之前提到的 lowbit 操作了,即对于下一次遍历的位置 x ′ x' x 有: x ′ = x − l o w b i t ( x ) x' = x - lowbit(x) x=xlowbit(x)

(2)元素修改

元素修改可以看作是区间查询的逆过程,即在右侧图示的树结构中,若修改其中的某一节点,则需要一层一层向上找到父节点(向右上方,与区间查询正好相反),并按照需要对每个父节点进行相同的修改处理。比如,对 节点 3 进行加 k k k 操作,则需要依次遍历 节点 3节点 4节点 8 并在遍历的过程中进行加 k k k 操作。在遍历下一个节点的过程中,只需要使用与区间查询类似的逆向过程即可,即对当前 x x x 位置节点,下一遍历节点 x ′ = x + l o w b i t ( x ) x' = x+lowbit(x) x=x+lowbit(x)

三、代码实现

class FenwickTree {
    private int[] tree;
    
    public FenwickTree(int n) {
        tree = new int[n+1];
    }
    
    public int lowbit(int x) {
        return x & (-x);
    }
    
    public void add(int i, int val) {
        while(i < tree.length) {
            tree[i] += val;
            i += lowbit(i);
        }
    }
    
    public int query(int i) {
        int res = 0;
        while(i > 0) {
            res += tree[i];
            i -= lowbit(i);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512485.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android studio使用glade7.5编译通过opencv官方例程camera_calibration

Opency官方例程是用glade4.2.1构建的&#xff0c;所以想使用glade7对官方例程重新构建。由于自己对android studio的glade架构不熟悉&#xff0c;走了不少弯路&#xff0c;刚开始使用glade7重新编译opencv官方例程&#xff0c;编译能通过&#xff0c;但是app总是会闪退。 下面这…

ArcGIS API for JavaScript 3.x 添加动态波纹标注

模拟波纹效果基于 arcgis 3.x, 先看效果图&#xff1a; 实现思路 波纹是由两个图层组成&#xff0c;圆点动态圆&#xff0c;主要借助于esri/geometry/Point和esri/symbols/SimpleMarkerSymbol,这两个类。 Point创建点&#xff0c; SimpleMarkerSymbol创建一个圆&#xff0c…

理化生实验室常用实验仪器清单及用途说明

理化生实验室除了常见的玻璃器皿&#xff0c;作为实验室中同样重要的一部分&#xff0c;实验仪器也是不可或缺&#xff0c;其可以有效地提高实验精度与效率。下面&#xff0c;就为大家盘点一下实验室都有哪些常见的实验仪器。 显微镜的用途主要用于放大微小物体成为人的肉眼所…

Acceptance-Rejection Sampling

Acceptance-Rejection Sampling 文章目录 Acceptance-Rejection Sampling[toc]1 接受拒绝采样2 Acceptance-Rejection 采样实现 1 接受拒绝采样 给定随机变量 X X X服从pdf为 f ( x ) f(x) f(x)的分布&#xff0c;例如 f ( x ) f(x) f(x)为正态概率密度函数&#xff0c;我们可…

js 字符串拼接的4种方法

一、使用连接符 把想要连接的字符串串起来 let shy 帅哥 let a 我是 shy console.log(a) // 我是帅哥 二、模板字符串 模板字符串&#xff08;template string&#xff09;是增强版的字符串&#xff0c;用反引号&#xff08;&#xff09;标识&#xff0c;特点&#xff1a…

【C++】-6- 模板初阶

文章目录 引入——泛型编程一、函数模板1.函数模板格式2.函数模板原理3.模板的实例化4.模板参数的匹配原则 二、类模板0.引入1.类模板的定义格式2.类模板的实例化 引入——泛型编程 如果我们需要实现不同数据类型的Swap函数&#xff0c;需要手写很多内容类似的结构。如下。 v…

【Gragph Data Mining】VF2算法 — 图同构匹配的算法

VF2算法是一种用于图同构匹配的算法&#xff0c;可以判断两个图是否同构。VF2算法最初由L. P. Cordella等人在1981年提出&#xff0c;后经过多次改进和优化&#xff0c;已成为常用的图同构匹配算法之一。VF2算法的基本思想是通过递归地搜索两个图的节点匹配&#xff0c;从而判断…

总结847

学习目标&#xff1a; 月目标&#xff1a;5月&#xff08;张宇强化前10讲&#xff0c;背诵15篇短文&#xff0c;熟词僻义300词基础词&#xff09; 周目标&#xff1a;张宇强化前3讲并完成相应的习题并记录&#xff0c;英语背3篇文章并回诵 每日必复习&#xff08;5分钟&#…

概率密度函数可视化

概率密度函数可视化 文章目录 概率密度函数可视化[toc]1 一维随机变量情形2 二维随机变量情形 1 一维随机变量情形 以正态概率密度函数为例&#xff0c;其中位置参数为 μ \mu μ&#xff0c;尺度参数为 σ \sigma σ&#xff0c; f ( x ) 1 2 π σ e − ( x − μ ) 2 2 σ…

ChatGPT聊天新玩意:如何让AI成为你的聊天好友?

目录 引言&#xff1a; 案例&#xff1a; 淄博旅游第一版本&#xff1a; 分析&#xff1a; 淄博旅游第二版本&#xff1a; 分析&#xff1a; 总结&#xff1a; 万能公式&#xff1a; 引言&#xff1a; ChatGPT是什么&#xff1f;今天用一句话概括&#xff0c;它就是新…

翻译: 面向开发人员的GPT提示工程 GPT Prompt Engineering for Developers

1. 提示指南Guidelines for Prompting 在本课中&#xff0c;您将练习两个提示原则及其相关策略&#xff0c;以便为大型语言模型编写有效的提示。 In this lesson, you’ll practice two prompting principles and their related tactics in order to write effective prompts …

7搜索管理

7搜索管理 7.1 准备环境 7.1.1 创建映射 创建xc_course索引库。 创建如下映射 post&#xff1a;http://localhost:9200/xc_course/doc/_mapping 参考 “资料”–》搜索测试-初始化数据.txt { "properties": { "description": { "type": &…

C语言操作符详解

该内容全部代码请看&#xff1a;gitee仓库 第一部分&#xff1a; 板书部分&#xff1a; 1、操作符的分类&#xff1a; 注意&#xff1a; 移位操作符和位操作符 单目操作符中有sizeof 逗号表达式 2、算术操作符&#xff1a; 注意&#xff1a; 除法的使用 取模运算 3、移位操…

485接口的温湿度传感器和RJ45接口的温湿度传感器选择分析

工业以太网RJ45接口 网口温湿度传感器和RS485信号输出温湿度传感器的分析对比 主要适用场合&#xff1a;大型厂房、跨区域机房、多机房、机柜、数据机房、服务器机房、大数据中心、户外电站等 主要区别&#xff1a;以太网温湿度传感器输出信号RJ45&#xff0c;RS485温湿度传…

【JAVA面试】缓存穿透、缓存击穿、缓存雪崩

提示&#xff1a;文章先作为初版&#xff0c;等后续时间充足后&#xff0c;补充更深的内容 文章目录 缓存穿透、缓存击穿、缓存雪崩一、区别二、线程安全问题 缓存穿透、缓存击穿、缓存雪崩 一、区别 缓存穿透&#xff08;Cache Penetration&#xff09;&#xff1a; 缓存穿…

展会邀请丨虹科诚邀您5月12日于北京参与制药行业质量控制技术论坛

2023年上半年&#xff0c;虹科圆满举办了成都CPQC与杭州药安大会&#xff0c;在两场顺利进行的展会上&#xff0c;虹科的产品广受青睐&#xff0c;也获得了许多客户的认可与信赖&#xff0c;虹科也将继续以优质的产品和解决方案解决您的问题。 5月12-5月13日&#xff0c;虹科将…

卷积神经网络(CNN):基于PyTorch的遥感影像、无人机影像的地物分类、目标检测、语义分割和点云分类

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。随着小卫星星座的普及&#xff0c;对地观测已具备多次以上的全球覆盖…

arm安装pyrealsense

arm安装pyrealsense – Step 1 – conda install numba pip install opencv-python pip install scipy – Step 2 pyrealsense2 – 参考 https://github.com/35selim/RealSense-Jetson 编译安装pyrealsense2 git clone -b v2.50.0 --depth1 https://github.com/IntelRealSens…

【Java】哈希冲突(哈希碰撞)

文章目录 为什么发生哈希冲突&#xff08;哈希碰撞&#xff09;能否完全避免哈希冲突常用处理哈希冲突的方法1.开放地址法1.1线性探测再散列缺点&#xff1a;二次聚集 1.2二次探测再散列1.3伪随机探测再散列 2.再哈希地址法3.链地址法4.建立公共溢出区 为什么发生哈希冲突&…

2C 兼容和小技巧 合集

这里写自定义目录标题 2C 兼容小技巧 合集修改input date默认框的小图标 2C 兼容小技巧 合集 以前一直是2b端没遇到过啥兼容性 或者 奇奇怪怪改UI的地方&#xff0c;现在换成C端业务&#xff0c;就在这里记录下遇到的奇奇怪怪的需求以及解决办法吧。 这篇文章争取 长久更新&am…