3.6.树状数组

news2025/1/19 13:45:07

树状数组

基本原理

树状数组(Binary Indexed Tree,简称 BIT)是一种高效的数据结构,它可以在O(log n)的时间复杂度下实现对数组的单点更新和区间求和操作。

前置知识

  • lowbit(int x) 函数:计算 x 的最低位的 1 及其后面的 0 组成的数,例如 lowbit(6)(二进制为 110)等于 2(二进制为 10)。
  • 在树状数组中,i元素的右父节点为i+lowbit(i),左父节点为i-lowbit(i)

核心操作

1. 单点更新

当更新数组中某个元素的值时,需要更新树状数组中与之相关的节点。对于更新操作 update(int index, int val),从 index 开始,不断向上更新父节点,更新的规则是将 index 加上 index & -index,直到超出数组范围。

// 单点更新操作,将位置 index 的元素值增加 val
    void update(int i, int val) {
        while (i <= n) {
            tree[i] += val;
            i += lowbit(i);
        }
    }
  • void update(int i, int val): 定义一个公共成员函数 update,用于在树状数组的指定位置 i 增加一个值 val
  • while (i <= n): 开始一个循环,只要 i 小于或等于 n,就继续执行循环。
  • tree[i] += val;: 将值 val 加到向量 tree 的第 i 个位置。
  • i += lowbit(i);: 更新索引 i,使其指向下一个需要更新的节点。lowbit(i) 返回 i 的最低有效位,这个操作确保了树状数组的更新操作能够正确地影响所有相关的节点。
2. 区间求和

对于查询区间 [1, index] 的和,从 index 开始,不断向下查找子节点,将结果累加,查找的规则是将 index 减去 index & -index,直到 index 为 0。

// 区间求和操作,求 [1, i] 的和
    int query(int i) {
        int sum = 0;
        while (i > 0) {
            sum += tree[i];
            i -= lowbit(i);
        }
        return sum;
    }

对于查询区间 [l, r] 的和,我们只需要分别求出区间[1, l] 和区间[1, r] 进行相减即可

// 区间求和操作,求 [l, r] 的和
    int query(int l, int r) {
        return query(r) - query(l - 1);
    }

代码实现

#include <iostream>
#include <vector>

using namespace std;

class BinaryIndexedTree {
private:
    vector<int> tree;
    int n;

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

public:
    BinaryIndexedTree(int size) {
        n = size;
        tree.resize(n + 1,0);
    }

    // 单点更新操作,将位置 index 的元素值增加 val
    void update(int i, int val) {
        while (i <= n) {
            tree[i] += val;
            i += lowbit(i);
        }
    }

    // 区间求和操作,求 [1, i] 的和
    int query(int i) {
        int sum = 0;
        while (i > 0) {
            sum += tree[i];
            i -= lowbit(i);
        }
        return sum;
    }

    // 区间求和操作,求 [l, r] 的和
    int query(int l, int r) {
        return query(r) - query(l - 1);
    }
};

int main() {
    BinaryIndexedTree bit(10);
    bit.update(1, 1);
    bit.update(2, 2);
    bit.update(3, 3);
    bit.update(4, 4);
    bit.update(5, 5);
    bit.update(6, 6);
    bit.update(7, 7);
    bit.update(8, 8);
    bit.update(9, 9);
    bit.update(10, 10);

    cout << bit.query(1, 10) << endl; // 55

    return 0;
}

代码解释

  • BinaryIndexedTree类:
    • bit 是存储树状数组的向量,n 是数组的长度。
    • lowbit(int x) 函数:计算 x 的最低位的 1 及其后面的 0 组成的数,例如 lowbit(6)(二进制为 110)等于 2(二进制为 10)。
    • update(int index, int val)函数:
      1. index 开始,不断更新 bit[index] 的值。
      2. index += lowbit(index); 用于找到下一个需要更新的节点,直到 index 超出数组范围。
    • query(int index)函数:
      1. index 开始,将 bit[index] 的值累加到 sum 中。
      2. index -= lowbit(index); 用于找到下一个需要累加的节点,直到 index 为 0。

应用场景

  • 动态更新和查询:当需要对数组进行频繁的单点更新和区间求和操作时,树状数组比普通的数组实现更高效,例如在数据频繁更新的统计系统中,如在线游戏中的玩家得分更新和排名统计。
  • 求逆序对:可以将数组元素离散化,然后使用树状数组统计每个元素之前比它大(或小)的元素的数量,从而计算逆序对的数量。

使用树状数组可以有效地解决一些动态更新和区间求和的问题,提高程序的运行效率,尤其是在数据规模较大时,它能显著降低时间复杂度。

注意事项

  • 树状数组的索引通常从 1 开始,因此在存储和操作时需要注意数组元素的偏移。
  • 对于不同的问题,需要根据具体情况对树状数组的更新和查询操作进行灵活运用,有时可能需要对原数组进行一些预处理,如离散化等。

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

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

相关文章

Java-数据结构-二叉树习题(1)

对于二叉树的学习&#xff0c;主要的还是得多多练习~毕竟二叉树属于新的知识&#xff0c;并且也并不是线性结构&#xff0c;再加上经常使用递归的方法解决二叉树的问题&#xff0c;所以代码的具体流程还是无法看到的&#xff0c;只能通过画图想象&#xff0c;所以还是必须多加练…

(二)afsim第三方库编译(qt编译)

注意&#xff1a;源码编译的路径不能有中文否则报错&#xff0c;压缩包必须用官网下载的xz格式解压的才可以&#xff0c;否则sudo ./configure命令找不到 先编译openssl3.1.1软件包&#xff0c;否则编译的qt库将不支持network&#xff0c;相关库的编译(上文&#xff08;一&…

【QT用户登录与界面跳转】

【QT用户登录与界面跳转】 1.前言2. 项目设置3.设计登录界面3.1 login.pro参数3.2 界面设置3.2.1 登录界面3.2.2 串口主界面 4. 实现登录逻辑5.串口界面6.测试功能7.总结 1.前言 在Qt应用程序开发中&#xff0c;实现用户登录及界面跳转功能是构建交互式应用的重要步骤之一。下…

【docker踩坑记录】

docker踩坑记录 踩坑记录(持续更新中.......)docker images 权限问题 踩坑记录(持续更新中…) docker images 权限问题 permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head "http://%2Fvar%2Frun%2Fdocker.s…

搜维尔科技:Xsens人形机器人解决方案的优势

Xsens 致力于推动人形机器人技术的发展&#xff0c;塑造机器人与人类环境无缝融合的未来&#xff0c;通过创新精确和协作&#xff0c;协助生产和服务&#xff0c;改善人类生活和产业。 Xsens通过人形跟随捕捉详细的人体运动数据&#xff0c;使机器人能够学习类人的动作&#x…

国内微电子(集成电路)领域重点高校的特色与优势

本文旨在梳理国内微电子&#xff08;集成电路&#xff09;领域重点高校的特色与优势&#xff0c;为有志于从事相关领域的学生提供参考。文章将从学科特色、科研实力&#xff08;以ISSCC论文为参考之一&#xff09;、行业认可度等方面进行分析&#xff0c;并强调实验室、导师、研…

leetcode707-设计链表

leetcode 707 思路 本题也是用了虚拟头节点来进行解答&#xff0c;这样的好处是&#xff0c;不管是头节点还是中间的节点都可以当成是中间节点来处理&#xff0c;用同一套方法就可以进行处理&#xff0c;而不用考虑太多的边界条件。 下面题目中最主要的实现就是添加操作addA…

数据结构-栈队列OJ题

文章目录 一、有效的括号二、用队列实现栈三、用栈实现队列四、设计循环队列 一、有效的括号 (链接&#xff1a;ValidParentheses) 这道题用栈这种数据结构解决最好&#xff0c;因为栈有后进先出的性质。简单分析一下这道题&#xff1a;所给字符串不是空的也就是一定至少存在一…

MindAgent:基于大型语言模型的多智能体协作基础设施

2023-09-18 &#xff0c;加州大学洛杉矶分校&#xff08;UCLA&#xff09;、微软研究院、斯坦福大学等机构共同创建的新型基础设施&#xff0c;目的在评估大型语言模型在游戏互动中的规划和协调能力。MindAgent通过CuisineWorld这一新的游戏场景和相关基准&#xff0c;调度多智…

近红外简单ROI分析matlab(NIRS_SPM)

本次笔记主要想验证上篇近红外分析是否正确&#xff0c;因为叠加平均有不同的计算方法&#xff0c;一种是直接将每个通道的5分钟实时长单独进行叠加平均&#xff0c;另一种是将通道划分为1分钟的片段&#xff0c;将感兴趣的通道数据进行对应叠加平均&#xff0c;得到一个总平均…

开发神器之cursor

文章目录 cursor简介主要特点 下载cursor页面的简单介绍切换大模型指定ai学习的文件指定特定的代码喂给ai创建项目框架文件 cursor简介 Cursor 是一款专为开发者设计的智能代码编辑器&#xff0c;集成了先进的 AI 技术&#xff0c;旨在提升编程效率。以下是其主要特点和功能&a…

电脑风扇声音大怎么办? 原因及解决方法

电脑风扇是电脑的重要组件之一&#xff0c;它的作用是为电脑的各个部件提供冷却&#xff0c;防止电脑过热。然而&#xff0c;有时候我们会发现电脑风扇的声音特别大&#xff0c;不仅影响我们的使用体验&#xff0c;也可能是电脑出现了一些问题。那么&#xff0c;电脑风扇声音大…

SpringBoot错误码国际化

先看测试效果&#xff1a; 1. 设置中文 2.设置英文 文件结构 1.中文和英文的错误消息配置 package com.ldj.mybatisflex.common;import lombok.Getter;/*** User: ldj* Date: 2025/1/12* Time: 17:50* Description: 异常消息枚举*/ Getter public enum ExceptionEnum {//…

软考高级5个资格、中级常考4个资格简介及难易程度排序

一、软考高级5个资格 01、网络规划设计师 资格简介&#xff1a;网络规划设计师要求考生具备全面的网络规划、设计、部署和管理能力&#xff1b;该资格考试适合那些在网络规划和设计方面具有较好理论基础和较丰富从业经验的人员参加。 02、系统分析师 资格简介&#xff1a;系统分…

如何通过 Apache Airflow 将数据导入 Elasticsearch

作者&#xff1a;来自 Elastic Andre Luiz 了解如何通过 Apache Airflow 将数据导入 Elasticsearch。 Apache Airflow Apache Airflow 是一个旨在创建、安排&#xff08;schedule&#xff09;和监控工作流的平台。它用于编排 ETL&#xff08;Extract-Transform-Load&#xff0…

STM32 学习笔记【补充】(十)硬件I2C读写MPU6050

该系列为笔者在学习STM32过程&#xff08;主线是江科大的视频&#xff09;中的记录与发散思考。 初学难免有所纰漏、错误&#xff0c;还望大家不吝指正&#xff0c;感谢~ 一、I2C 外设简介 I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种多主多从的串行通信协议…

QT信号槽 笔记

信号与槽就是QT中处理计算机外设响应的一种机制 比如敲击键盘、点击鼠标 // 举例&#xff1a; 代码&#xff1a; connect(ls,SIGNAL(sig_chifanla()),ww,SLOT(slot_quchifan())); connect(ls,SIGNAL(sig_chifanla()),zl,SLOT(slot_quchifan()));connect函数&#xff1a;这是…

【React】插槽渲染机制

目录 通过 children 属性结合条件渲染通过 children 和 slot 属性实现具名插槽通过 props 实现具名插槽 在 React 中&#xff0c;并没有直接类似于 Vue 中的“插槽”机制&#xff08;slot&#xff09;。但是&#xff0c;React 可以通过 props和 children 来实现类似插槽的功能…

openharmony电源管理子系统

电源管理子系统 简介目录使用说明相关仓 简介 电源管理子系统提供如下功能&#xff1a; 重启服务&#xff1a;系统重启和下电。系统电源管理服务&#xff1a;系统电源状态管理和休眠运行锁管理。显示相关的能耗调节&#xff1a;包括根据环境光调节背光亮度&#xff0c;和根…

数据库(中)11讲

用颜色、有否下划线对应&#xff01; E-R图