<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Binary Indexed Tree &#8211; HU Xiaoxu</title>
	<atom:link href="https://blog.ihuxu.com/tag/binary-indexed-tree/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.ihuxu.com</link>
	<description>a software engineer&#039;s blog</description>
	<lastBuildDate>Sat, 21 Jun 2025 01:45:55 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>
	<item>
		<title>树状数组（Binary Indexed Tree）</title>
		<link>https://blog.ihuxu.com/binary-indexed-tree/</link>
					<comments>https://blog.ihuxu.com/binary-indexed-tree/#respond</comments>
		
		<dc:creator><![CDATA[HU Xiaoxu]]></dc:creator>
		<pubDate>Thu, 10 Oct 2019 16:04:30 +0000</pubDate>
				<category><![CDATA[Advanced Data Structure]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Data Structure and Algorithm]]></category>
		<category><![CDATA[Binary Indexed Tree]]></category>
		<category><![CDATA[Original]]></category>
		<guid isPermaLink="false">https://blog.ihuxu.com/?p=12051</guid>

					<description><![CDATA[树状数组或二叉索引树（英语：Binary Indexed Tree），又以其发明者命名为Fenwick树。其初衷是解决数据压缩里的累积频率（Cumulative Frequency）的计算问题，现多用于高效计算数列的前缀和， 区间和。它可以以的时间得到任意前缀和，并同时支持在时间内支持动态单点值的修改。空间复杂度。 摘自维基百科 文章先介绍低位运算（lowbit）的基本知识，再提及如何将一个整数划分为个区间的运算过程，进而延展到如何将线性序列以树行结构进行存取，接着介绍了高级数据结构——树状数组的两个基本操作——查询前缀和与单点增加，最后介绍了树状数组的一个应用——求解逆序对数。 lowbit（低位）运算 定义为非负整数在二进制表示下“最低位的1及其后边所有的0”构成的数值。 比如：，其二进制表示为 ，则其低位。 公式 如何计算一个整数中二进制表示下所有位是1的数值？ 比如，则其二进制表示下所有位是1的数值有：，。 朴素算法需要枚举整数中所有的位，时间复杂度为，为整数的二进制表示下的位数。 为了高效获取二进制表示下所有位是1的数值，可以利用运算，得到时间复杂度，为二进制表示下为1的位的个数。 比如，；接着另，则；接着另，停止。 为了得到的第几位为1，可以对2和8分别取对数，即, 。由于C++ math.h 库的函数是以为底的实数运算，并且复杂度常数较大，所以可以通过预处理，利用哈希表来代替运算。 代码 树状数组 假设整数，其二进制表示形式为： 代表二进制表示下位为1的索引下标值，且假设。 那么，可以将区间划分成个小区间 比如，，那么区间可以划分成, 和，其区间长度分别为, 和. 利用运算计算区间： 树状数组是基于以上思想的数据结构，基本用途是维护序列的前缀和。 那么，假设有序列，现在的问题就是如何将这个序列划分成个小区间。不妨，利用序列的索引值（以1为起点开始计数），根据上述计算区间的方式，将其以如下树形结构展开。 此时，以树形结构展开的序列A中的每一个节点都对应着树状数组中的一个值。那么这个值为以当前节点为根的子树中所有节点值的总和。 接着，我们看下以树形结构展开的树状数组是什么样的。 上图中最大的区别是某些节点中的值发生了变化。这是因为，在以树形结构展开的树状数组中的每一个值代表的是一个区间的总和。这个区间即为我们上述求解的区间，比如一个整数7，可以将其划分成, 和三个小区间。那么，这三个小区间的右端值作为索引对应的树状数组中的值即为当前区间元素的总和。 比如对应的树状数组的值为（BIT Value）10，它代表这个区间的和。 再比如对应的树状数组的值为11，它代表这个区间的和。 基本操作 树状数组支持两个基本操作——查询前缀和，单点增加。 查询前缀和 在寻求序列A的前n项的前缀和时，等于n代表的个区间的总和。 单点增加 观察父子节点的关系，可以推算出，父节点的索引parent(i)，为其子节点索引值 + 其低位——。 关于查询前缀和与单点增加的计算过程，可以观看下面视频展示的动画。 树状数组与逆序对 对于一个序列，如果，并且，那么则称与构成逆序对。利用树状数组数据结构可以求解序列中的逆序对个数。 在每一次更新（）树状数组时，以元素的值作为树状数组的索引，更新的值为+1，代表个数。 在每一次获取（）逆序对数时，存在于树状数组中的元素的索引值都比当前元素的大（逆序遍历），那么自然获取到的树状数组的值即为索引值比当前元素的大，且值比当前元素的小的个数。 注意，上述的求解过程时，如果序列A的值范围较大时，那么需要离散化处理。 参考]]></description>
		
					<wfw:commentRss>https://blog.ihuxu.com/binary-indexed-tree/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
