树状数组详解

2023-11-16

# Markdown版本

请点击这个链接:树状数组(Markdown版本)_xiji333的博客-CSDN博客

什么是树状数组:

树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。

它能用来干什么:

最经典的应用就是查询某一段区间元素的和,而且支持在线修改操作。如果没有修改操作,就没必要用树状数组了。

它和线段树有什么关系:

实际上树状数组就是没有右儿子的线段树,它实现起来比线段树简单,而且效率更高,空间占用的也更少。但是能用树状数组解决的问题,基本上都能用线段树解决。(反过来就不是了)

我还是不知道树状数组是什么:

不多解释了,先上几张图:

我们用数组A表示原序列:A1、A2……An

用数组C代表树状数组,从上图中我们可以发现:

C1=A1    C2=A1+A2    C3=A3    C4=A1+A2+A3+A4    C5=A5    C6=A5+A6    C7=A7    C8=A1+A2+A3+A4+A5+A6+A7+A8

对应数组C下标的二进制表示:

C1的下标1的二进制表示 1 末尾有0个连续的0 该节点管理1个元素

C2的下标2的二进制表示 10 末尾有1个连续的0 该节点管理2个元素

C3的下标3的二进制表示 11 末尾有0个连续的0 该节点管理1个元素

C4的下标4的二进制表示 100 末尾有2个连续的0 该节点管理4个元素

……

由此我们得到一个规律:我们设i的二进制表示的末尾有k个连续的0,那么Ci管理2^k个元素。那么有什么办法可以很快的算出来2^k呢?我们有一个名为lowbit的神奇操作:x&(-x) 就是我们想要的答案。且对于节点i,i+lowbit(i)就是节点i的父节点

知道这些有什么用呢:

我们可以对照上图,若我们求[1,7]的区间和,那么sum=C7+C6+C4,即三次操作就得到了我们想要的结果,这也是为什么查询的复杂度是O(lgn)的,那么我们看看lowbit发挥了怎样的作用吧:7-lowbit(7)=6     6-lowbit(6)=4    4-lowbit(4)=0。可以发现,我们求和的操作就是从区间右端点r开始,不断地累加Cr,同时对r作lowbit操作。那么修改操作呢,就逆着来,即从要开始的子节点i开始,不断修改Ci,同时对i做lowbit操作。有人可能会问,你这求的是[1,r]的和啊,我要求[l,r]的和怎么办呢?很简单,把[1,r]和[1,l-1]的和均求出来,然后用前者减去后者即可得到答案。

树状数组的基本操作:

这里我以求某段区间和作为例题来介绍一下线段树的基本操作。(注意 树状数组的下标是从1开始的)

lowbit操作:

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

更新操作:(单点修改)

void update(int i,int v)
{
	for(;i<=n;i+=lowbit(i))
		tree[i]+=v;
}

查询操作:

int sum(int l)
{
	int s=0;
	for(;l;l-=lowbit(l))
		s+=tree[l];
	return s;
}

一位树状数组的内容就到这里了~大家可以做题体会一下~

下面我们来说说二维树状数组:

举一个简单的例子,我们有16个元素:A1、A2、A3、A4、……A16构成了一个4*4的矩阵,我想查询某个矩阵内所有元素的和,并且可能会修改该矩阵的某个元素怎么做呢?朴素算法肯定是遍历统计和,复杂度O(n^2),那有没有O((lgn)^2)的算法呢?肯定有,这就是我们要介绍的二维数组,首先要知道对于Tree[i][j]的每一个Tree[i]肯定是一个一维的树状数组,但是其存储的东西可能跟你想的有点区别:(并不是简简单单的Tree[1]管理A1-A4   Tree[2]管理A5-A8哦)

我们先写出四个一维的树状数组:

tree1[1]=A1    tree1[2]=A1+A2     tree1[3]=A3     tree1[4]=A1+A2+A3+A4

tree2[1]=A5    tree2[2]=A5+A6     tree2[3]=A7     tree2[4]=A5+A6+A7+A8

tree3[1]=A9    tree3[2]=A9+A10    tree3[3]=A11     tree3[4]=A9+A10+A11+A12

……

然后再写出我们的二维树状数组:

Tree[1][1]=A1      Tree[1][2]=A1+A2       Tree[1][3]=A3       Tree[1][4]=A1+A2+A3+A4

Tree[2][1]=A1+A5       Tree[2][2]=A1+A2+A5+A6        Tree[2][3]=A3+A7      Tree[2][4]=A1+A2+A3+A4+A5+A6+A7+A8

Tree[3][1]=A9      Tree[3][2]=A9+10        Tree[3][3]=A11     Tree[3][4]=A9+A10+A11+A12

……

也就是说Tree[i]维护的是:treei+tree(i-1)+……+tree(i-lowbit(i)+1) 比如上面Tree[2]维护的就是tree2和tree1

那么我们求这个矩阵从第1行到第x行,第1列到第y列的操作就很简单了:(就是原来的一维变成了二维)

至于怎么求中间的某个矩阵的和就留给大家思考了~

void add(int x,int y,int v)
{
	for(int i=x;i<=n;i+=lowbit(i))
		for(int j=y;j<=n;j+=lowbit(j))
			tree[i][j]+=v;
}

int query(int x,int y)
{
	int sum=0;
	for(int i=x;i;i-=lowbit(i))
		for(int j=y;j;j-=lowbit(j))
			sum+=tree[i][j];
	return sum;
}

树状数组处理RMQ问题:

修改:

void updata(int x)
{
	int lx,i;
	while x<=n)
	{
		h[x]=a[x];
		lx=lowbit(x);
		for(i=1;i<lx;i<<=1)
			h[x]=max(h[x],h[x-i]);
		x+=lowbit(x);
	}		
}

查询:

int query(int x,int y)
{
	int ans=0;
	while(y>=x)
        {
		ans=max(a[y],ans);
		y--;
		for(;y-lowbit(y)>=x;y-=lowbit(y))
			ans=max(h[y],ans);
	}
	return ans;
}

针对区间[1,r]的查询:

int query(int r)//查询[1,r]
{
    int ans=INF;
    while(r)
    {
        ans=min(ans,tree[r]);
        r-=lowbit(r);
    }
    return ans;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树状数组详解 的相关文章

  • 【每日一题】ABC194E-Mex Min

    题目内容 原题链接 给定一个长度为 n n n 的整数数组 a a a 求所有长度为 m m
  • 【每日一题】ABC194E-Mex Min

    题目内容 原题链接 给定一个长度为 n n n 的整数数组 a a a 求所有长度为 m m
  • 基础算法题——牛牛种花(高效、降维、离散化、树状数组)

    牛牛种花 题目链接 这道题还是挺有意思的 呵呵 解题思路 高效 利用结构体存储数据 struct node int x y id a N lt lt 1 利用 id 来记录每个节点是查询或是种树 若为查询则给予编号 从 1 开始编号 否则置
  • 1800*D. Nested Segments(数组数组&&离散化)

    解析 按照右端点进行排序 这样某个区间包含的区间只能是在其前面的区间中 所以维护左端点 x 的出现次数 这样我们在查询某个区间 x y 的时候 只需要求 x y 之间包含多少个前面区间的 x 即可 前缀和 因为 前面区间的 y 显然小于当前
  • Color the ball

    点击打开链接 Problem Description N个气球排成一排 从左到右依次编号为1 2 3 N 每次给定2个整数a b a lt b lele便为骑上他的 小飞鸽 牌电动车从气球a开始到气球b依次给每个气球涂一次颜色 但是N次以后
  • Tokitsukaze and Colorful Tree【树状数组+离线+dfs】

    题目链接 HDU 6793 题意 有N个点的树 每个点有颜色和权值 现在有两种操作 要求的是树上的同种颜色的非祖先与子孙节点的两点的异或和 更改某个点权值为v 将某个点的颜色更改为c 于是我们可以这样考虑 现在将所有的颜色离线下来 每次我们
  • 洛谷 P3374 【模板】树状数组 1

    题目链接 https www luogu com cn problem P3374 include
  • 区间查询(树状数组之差点问线问题)

    1110 区间查询 时间限制 2 Sec 内存限制 32 MB 提交 162 解决 62 提交 状态 题目描述 食堂有N个打饭窗口 现在正到了午饭时间 每个窗口都排了很多的学生 而且每个窗口排队的人数在不断的变化 现在问你第i个窗口到第j个
  • REQ 【CodeForces - 594D】【树状数组+离线查询+区间思维】

    题目链接 很好的一道题 昨晚上推的 今天由于代码能力太弱敲了半天 再不断的找到自己思维的BUG 于是RE了一发 T了一发 WA了一发 就Ac了 还不错 那我们来讲解一下题目的思路 我们知道对于一个值的欧拉函数值 就是它的值去乘上它所有的质数
  • 【每日一题】补档 ABC309F - Box in Box

    题目内容 原题链接 给定 n n n 个箱子 问是否存在一个箱子 x x x 是否可以放到另一个箱子 y
  • 【算法】树状数组维护总结

    本文仅对树状数组的使用作一个总结 并非讲解 这里的操作都对长度为 n n n 的数组 a a a 进行操作 单点修改 区间查询 暴力做法 修改
  • 二叉搜索树(树状数组)

    计数函数 程序 int lowbit int k return k k 功能 可视为每个节点的编号函数 加和函数 程序 int sum int x int ret 0 while x gt 0 ret c x x lowbit x retu
  • [CTSC2008]网络管理Network【树状数组+主席树】

    题目链接 题意 有一棵N个点的树 每个点有对应的权值 现在有这样的操作 0 a b 将a点的权值改成为b k a b 询问a到b的链上第k大的权值是几 我们可以用dfs序的树上差分的方式来解决这个问题 可以发现 求u到v的信息 其实就是求u
  • 幻想乡的日常【树状数组+离线操作】

    题目链接 给出N个点的树 编号为1 N 每次的查询为 L R 想知道编号在 L R 内的所有的结点的会被分成多少个连通块 给出一条性质 连通块数量 点数 边数 点数很方便的可以计算 就是 R L 1 那么 如何计算边数呢 我们知道 每条边有
  • 树状数组详解

    Markdown版本 请点击这个链接 树状数组 Markdown版本 xiji333的博客 CSDN博客 什么是树状数组 树状数组 Binary Indexed Tree B I T Fenwick Tree 是一个查询和修改复杂度都为lo
  • Crazy Thairs【树状数组+高精度+DP思想】

    题目链接 POJ 3378 题意 有N个点 问的是要求组成一个长度为5的上升子序列的组成有多少种 最搞事情的是这道题不用取模 所以 是一定会爆long long的 首先 很容易想到一点就是我们可以开一个dp maxN 5 表示的是 dp i
  • 【模板】树状数组

    文章目录 1 概述 2 原理 3 实现 3 1 lowbit x 3 2 查询前缀和 3 3 单点增加 4 初始化 1 概述 树状数组 Binary Indexed Trees 其基本用途是维护序列的前缀和 对于给定的序列 a a
  • 【树状数组该回炉重造了】Codeforces Round #813 (Div. 2) E2. LCM Sum (hard version)

    参考题解 题意 T T T 组数据 每组数据给定 l l l 和 r r
  • 树状数组笔记

    数组 前缀和 树状数组的区别 数组 修改某点O 1 求区间O n 前缀和 修改某点O n 求区间O 1 树状数组 修改某点O logn 求区间O logn 树状数组采取折中的方式 降低整体的时间复杂度 由于算法复杂度取决于最坏的情况的复杂度
  • 二分答案总结&例题解析

    对于二分我们最初的了解 就是在一个一次函数中 对于要求的点 x y 已知y 对于包含x值的区间二分 根据函数值与y比较 逐步靠近要求的点 直到最终求出要求的点 在程序执行时 二分的时间复杂度为logn 可以极大的减少查找的时间 二分的应用

随机推荐

  • 运放中接电容的作用

    运放概述 案例讲解 运算分析 一 基本概念 反向放大器 优点 两个输入端电位始终近似为零 同相端接地 反相端虚地 只有差模信号 抗干扰能力强 缺点 输入阻抗很小 等于信号到输入端的串联电阻的阻值 同相放大器 优点 输入阻抗和运放的输入阻抗相
  • 《JavaScript高级程序设计(第四版)》红宝书学习笔记(2)(第四章:变量、作用域与内存)

    个人对第四版红宝书的学习笔记 不适合小白阅读 这是part2 持续更新 其他章节笔记看我主页 记 的表示是ES6新增的知识点 记 表示包含新知识点 第四章 变量 作用域与内存 4 1 原始值与引用值 ECMAScript变量可以包含两种不同
  • C获取linux系统环境变量方法(Environment Variables)

    主要有三种方法 都很简单 1 一个单纯c语言获取的方式 span style font family none font size 14px include span
  • Java系列8—对象创建的内存分配和构造方法

    对象的创建 类和对象的区别 面向对象 java语言的核心机制 最重要的内容 java语言的特色 面向过程和面向对象的区别 面向过程 主要关注点是 实现的具体过程 因果关系 面向对象 主要关注对象 独立体 能完成哪些功能 优点 耦合度低 扩展
  • 态势感知(SIP)

    SIP态势感知 一 SIP态势感知概述 1 业界标准 数据来源 gt 智能分析 gt 安全可视 gt 协同响应 通过日志采集探针和流量传感器分别进行不同系统日志和流量日志的采集和处理任务 通过对海量数据进行多维度快速 自动化的关联分析发现本
  • 跨框架解决方案-Mitosis【问题与局限】

    不要定义与状态属性同名的变量 async方法不能定义在state内 函数不能通过引用直接传递给JSX回调函数 可以在回调函数中定义一个匿名函数 不能将 params 分配给 state 不能将函数输出分配给 state state不能被解构
  • dart 相关资源收集

    百丈高楼平地起 要想写好flutter 必先学号dart 资源 给 Android 开发者的 Dart 教程 学好 Dart 才能玩转 Flutter
  • ms-repeat 数据渲染后触发事件

    ms repeat 数据渲染后触发 data repeat rendered 例子 div class timebox h3 el year 年 el month 月 h3 ul li li ul div
  • MVC设计思想

    1 MVC思想的说明 经典MVC模式中 M是指业务模型 V是指用户界面 C则是控制器 使用MVC的目的是将M和V的实现代码分离 从而使同一个程序可以使用不同的表现形式 其中 View的定义比较清晰 就是用户界面 M model 业务模型 V
  • 24个笔画顺序表_语文老师整理:560个小学常用汉字笔画笔顺表!小学阶段多练习...

    今天给大家分享的是资深语文老师整理的学习资料 560个小学常用汉字笔画笔顺表 家里有小学生的家长 建议帮孩子存好 小学阶段多练习 不仅对语文学习的提高有帮助 还能培养孩子的语文素养 在小学语文的学习中 汉字是最基础的知识点 孩子在学习语文的
  • Codeforces Round #561 (Div. 2)ABC

    三个题 各位大佬别喷我 我很菜 A Silent Classroom There are n students in the first grade of Nlogonia high school The principal wishes
  • 【03】上下文

    基于智能 合约的安全企业对消费者供应链系统在农产品供应链中使用区块链和智能 合约进行追溯链上 链下 智能 合约的可扩展和隐私保护设计TinyEVM 低功耗物联网设备上的链下 智能 合约区块链技术中的智能 合约和用例概述Blockumulus
  • Java的8种基本数据类型

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 前言 Java数据类型分为两大类 基本数据类型 引用类型 如图所示 下面讲解的是Java的八种基本数据类型 一 按照数据类型来分 1 整
  • 西门子变频器SINAMICS S120电源模块分享

    西门子变频器SINAMICS S120系列 在工业领域中能胜任各种要求严格的驱动控制任务 为用户提供简单有效的驱动控制过程 西门子变频器SINAMICS S120系列可以配置电源模块 来为西门子变频器驱动控制系统提供稳定的电源保障 本文下面
  • 设计模式-模板方法

    文章目录 前言 模板方法模式简介 Java代码示例 模板方法使用场景 模板方法使用场景 前言 当我们需要在一个算法的框架中定义算法的骨架 并将一些步骤的具体实现留给子类来完成时 模板方法模式是一种非常有用的设计模式 这篇博客将介绍模板方法模
  • install.packages(“hgu133a.db“)报错——解决办法

    问题描述 install packages hgu133a db WARNING Rtools is required to build R packages but is not currently installed Please do
  • Sqli-Labs Less1-16关详细讲解

    Sqli Labs Less1 16关详细讲解 一 首先介绍一下这个重要的数据库 information schema数据库 二 Sqli Labs靶场 Get传输方式 Less 1 Union Select注入 闭合符 Less 5 报错
  • freertos中空闲任务函数prvIdleTask()详解

    The Idle task 空闲任务函数 The portTASK FUNCTION macro is used to allow port compiler specific language extensions The equival
  • Verilog开源项目——百兆以太网交换机(一)架构设计与Feature定义

    Verilog开源项目 百兆以太网交换机 一 架构设计与Feature定义 声明 未经作者允许 禁止转载 博主主页 王 嘻嘻的CSDN主页 全新原创以太网交换机项目 Blog内容将聚焦整体架构 模块设计方面 更新周期可能会略慢 希望朋友们多
  • 树状数组详解

    Markdown版本 请点击这个链接 树状数组 Markdown版本 xiji333的博客 CSDN博客 什么是树状数组 树状数组 Binary Indexed Tree B I T Fenwick Tree 是一个查询和修改复杂度都为lo