首页 > 其他分享 >数据结构【树状数组】

数据结构【树状数组】

时间:2024-02-17 21:22:52浏览次数:28  
标签:数组 内含 树状 lowbit 端点 区间 数据结构

树状数组是线段树的衍生产物,牺牲了部分通用性,节约了空间,且大大减少了手写码量。

借助树状数组,我们可以用O(logN)的时间复杂度来实现给定序列中长度为n的区间中元素和的计算。

https://www.bilibili.com/video/BV1ce411u7qP/?spm_id_from=333.337.search-card.all.click&vd_source=5795184162077d9b7f04406dc36caa90
这个视频讲解树状数组得很形象,但不透彻,透彻的说法见下文。

从视频给出的可视化描述中,我们发现,对于一个长度为n的原序列而言,我们需要n/2个内含长度为1的树状数组元素(简称树元),还需要n/2/2个个长度为2的树元,以此类推,我们最终恰好需要n个树元构成的序列来存储原序列所含信息,其中每个树元所代表的区间的右端点都不同。

对于每一个树元,我们需要存储三个信息:所内含元素个数、所内含最后一个元素的下标、所内含元素的和。

但是,我们既然已经发现,我们需要存储的区间恰好有n个,并且这n个区间的右端点恰好不同,也就是说,唯一的右端点唯一对应着一个区间,而唯一的区间显然又唯一对应着一个区间长度。那么我们就可以建立一个右端点->区间长度的映射函数,恰好,lowbit(x)=x~(-x)这个不需要任何超参数的函数可以完成这个任务。这也就意味着,所内含元素个数和所内含最后一个元素的下标其实是一个信息,只要存储了后者,就可以用lowbit函数算出前者。

(至于lowbit为何能如此呢?这是因为我们把线段树转化为树状数组之后,所有树元的区间长度和右端点的关系都恰好和lowbit这个纯算术运算过程完全重合了,因此直接把这个函数拿过来用,至于这个伟大的巧合是谁发现的?想必是个大牛。但其实这倒也不完全是拉马努金式的发明,毕竟lowbit函数其实也可以通过数学手段直接从树状数组取区间的规则中直接反向推算出来,具体过程中文互联网上可能查不到,但无关主线且并不高深,我这里就不多赘述了)

因此,我们对于每一个树元,只需要存储两个信息:所内含最后一个元素的下标、所内含元素的和,即右端点序号和树元值。

注意到,右端点序号恰好是1~n,那么我们直接把对应右端点序号的树元值存入对应下标的数组空位中,我们就可以实现用下标本身来存储右端点序号,而用数组本身的存储空间来存储树元值。

这样的一个数组,便是树状数组了,对于树状数组T而言,T[i]是右端点为i,区间长度为lowbit(i)的原序列区间的和。

标签:数组,内含,树状,lowbit,端点,区间,数据结构
From: https://www.cnblogs.com/gongkai/p/18018432

相关文章

  • 【数据结构】串的表示与模式匹配算法
    串串是内容受限的线性表(栈和队列是操作受限的线性表)串(string)是零个或多个任意字符组成的有限序列S:串名a1a2a3...an:串值n:串长当n=0时,表示空串,空串用\(\phi\)表示子串:一个串中任意个连续字符组成的子序列(含空串)例如“abc”的子串有“”、“a”、“b”、"c"、"ab"......
  • 字符串、向量和数组
    一、字符串1.引入库include<string>usingstd::string;2.初始化strings(10,'c');//直接初始化strings1("hello");//直接初始化strings2="hello";//拷贝初始化3.操作(1)s+="world"//左值引用(返回值),避免拷贝(2)st......
  • 树状DP心得
    说一下近日所学的主要两种题型,一个是分叉情况问题,一种是树上背包问题。分叉情况问题具体的题可以参考小胖守皇宫和三色二叉树。点击查看代码小胖守皇宫#include<bits/stdc++.h>usingnamespacestd;constintN=2000;vector<int>son[N];intfa[N],h[N],f[N][3];//f[0]......
  • 2024-02-17-物联网C语言(2-数组)
    2.数组2.1数组的概念​ 数组是若干个相同类型的变量在内存中的有序存储集合。数组存储一组数据数组里面存储的数据类型必须是相同的数字在内存中会开辟一块连续的空间//定义了一个整型的数组a,a是数组的名字,数组中有10个元素,每个元素的类型都是int类型,而且在内存中连续......
  • 树状数组
    树状数组背景由于\(OIer\)们对于数据更高效的储存、修改和查询的需要,一种数据结构树状数组营运而生。介绍树状数组是一个查询和修改时间复杂度都为\(O(log(n))\)的数据结构,主要用于:数组的单点修改和区间查询在使用前缀和求区间和的算法中:如果可以做到在\(O(1)\)......
  • 关于一种维护凸包的根号数据结构
    本文介绍了笔者由一道题的根号做法受到启发,独自摸索出来的一个数据结构。由于笔者能力和精力有限,无法查找已有的资料,如果有哪位巨已经提出来了记得踩我一脚。介绍这个数据结构维护凸包,支持以下操作:\(O(\sqrt{n})\)在线加入/删除任意一条线段\(O(\sqrt{n}\log\sqrt{n})\)在......
  • 树状数组-三色二叉树 题解
    题目在这里————————————————————————————————三色二叉树首先题面写的很清楚了是一道树状数组题因为这题的输入方式很特别按二叉树序列所以在输入上要特殊处理如下voidread(intx){//读入+存图以左右子树为形式如l[x]=y即y为x左子树......
  • 查找数组中最大元素,数组的打印,反转
    需求查找数组中最大元素,数组的打印,反转;学习点方法retrun的数在主方法中要定义元素接收,如反转数组返回一个数组,main方法中要定义一个新的数组用来接收返回的数组;数组循环可以使用增强for循环反转数组的for循环可以同时定义i和j,同时一个递增一个递减代码实现package......
  • 数组成鸡
    数组成鸡题目描述小鸡有一个由整数组成的数组,小鸡可以对这个数组进行任意次(可以不进行)全数组每个数加一或全数组每个数减一的操作。现在,小鸡想让你回答$Q$次询问,每次询问给出一个整数$M$,你需要回答任意次(可以不操作)操作后是否可以使得给定数组的乘积等于给出的整数$M$。输......
  • 数据结构——链表
    链表(LinkedList)一种线性数据结构,其中的每个元素都是一个节点对象。各个节点通过“引用”(指针)相连接,引用中记录了下一个节点的内存地址,通过其可以定位并访问到下一个节点。链表对比数组有更好的灵活性,数组要求内存空间是连续的,但当数组非常庞大时,可能无法提供那么大的连续空间,同......