首页 > 其他分享 >树状数组(Binary Index Tree)

树状数组(Binary Index Tree)

时间:2023-11-09 20:11:06浏览次数:33  
标签:Index 树状 lowbit sum Tree 修改 add 数组 Binary

一、问题引入

Logu P3374
模版题--树状数组。
初始化一个数组,接下来进行若干次以下操作:

  1. 单点修改:将某个元素的值进行修改
  2. 区间访问:返回该区间的总和

问题分析

如果通过简单索引操作,“1”的时间复杂度为 O(1),“2”的时间复杂度为O(n),其中如果使用一个dp表的方式来存储前n项之和,那么“2”的时间复杂度为O(1),但是一旦要进行修改操作则变成\(O(n^2)\),显然,我们需要一种更有效的数据结构来维护我们的列表

二、树状数组

  我们是否可以这样想:如果我们构造一个数组,其第i个元素包含前i项之和,但是这样不适合经常修改的元素列表,我是否可以将列表划分成n份,用这n段的和来构造这个函数?
  显然,如果我们进行修改操作,对其中那个数组就还是回归到了原问题上面.因此,树状数组应运而生

Lowbit操作

假设x = \((10100100)_2\),则定义:

\[lobit(x) = (100)_2 = 4 \]

即lowbit(x)表示x的二进制下从左往右数第一个1及其后面所有0(个人理解,其实就是按2的次幂为间隔划分原序列数组,只不过正好有规律,不然以其他数的次幂划分也行)
由于有符号数字在计算机中以补码的形式存在,则\(-x = (01011011)_2 + 1_2 = (01011100)_2\),发现只有lowbit(x)相同,其余都不同,于是有:

\[lobit(x) = x\&-x \]

树状数组的构建

如图:
image
在原数组上面构建树状数组T[],观察到有如下规律:

  1. 对某一层数i,有lobit(x) = i,并且其子节点也为lowbit(x)
  2. 数最高为\(log_2 n +1\)
  3. 对于某一个子节点T[x],其父节点为:T[x+lowbit(x)]
  4. 前n个元素之和为T[n]+T[n-lowbit(n)]+T[n-lowbit(n)-lowbit(n-lowbit(n))]+....

经过如上规律,我们可以写出代码:

单点修改

void add(int x, int k) {
	for (; x <= n; x += x & -x) T[x] += k;
}

区间访问

int ask(int x) {
	int res = 0;
	for (; x; x -= x & -x) res += T[x];
	return res;
}

三、其他操作

区间修改、单点查询

我们构建一个树状数组,用来存放原数组的差分,此时该树状数组的前n项和为A[n],当我们需要对x-y之间加上或减去相同值是,在树状数组的两个元素之间只有第x个和第y+1个的值发生改变,于是只需添加:

add(x, k);
add(y+1, -k);

要进行单点查询只需求和即ask即可

区间修改、区间查询

我们知道在构建差分数组的情况下,前n项和为:

\[S = \sum_{i=1}^{x}\sum_{j=1}^{i}d[j] \]

如图:
image
有:

\[S = \sum_{i=1}^{x}\sum_{j=1}^{i}d[j] = (1+x)\sum_{i=1}^{x}d[i] - \sum_{i=1}^{x}id[i] \]

至于要在上面情况的基础上构建一个新的树状数组用来存储id[i]即可完成
于是有:

//区间修改
//d[i]操作不变,对新构建的id[i]:
add(x,x*k);
add(y+1,-(y+1)*k);

//区间访问:
res = (1+x)ask(x) - ask_new(x)

标签:Index,树状,lowbit,sum,Tree,修改,add,数组,Binary
From: https://www.cnblogs.com/C-qian/p/17822701.html

相关文章

  • [题解]CFgym103470E Paimon Segment Tree
    PaimonSegmentTree区间加,求一段时间内的区间平方和。\(n,m,q\le5\times10^4\)。对时间维差分一下,变成询问区间历史平方和。离线下来扫描线,扫描线维护时间维,数据结构维护序列维。考虑维护二元组\((a,s)\)表示当前位置值为\(a\),历史平方和为\(s\)。可以发现怎......
  • indexDB数据库快速入门
    indexDB简介indexDB本质上就是存储数据,优点不受大小限制,当数据大于>5MB时我们无法通过localStorage、cookie(只能存4k)存储//连接数据库(连接的过程是一个异步的)window.indexedDB.open('库名称','库版本号')>=0constrequest=window.indexedDB.open('......
  • vue 项目使用element ui 中tree组件 check-strictly 用法
    属性check-strictly:   在显示复选框的情况下,是否严格遵循父子互相关联的做法,默c认为false。   默认false,父子关联。      点击父节点,其下子节点全部统一跟随父节点变化,点击子节点,子节点部分勾选时,父节点处于半选状态。   设置为true,严格遵循......
  • Set---SortedSet-NavigableSet-TreeSet
    SortedSet概述A{@linkSet}thatfurtherprovidesa<i>totalordering</i>onitselements.Theelementsareorderedusingtheir{@linkplainComparablenaturalordering},orbya{@linkComparator}typicallyprovidedatsortedsetcreationtime.......
  • Map---SortedMap&NavigableMap&TreeMap
    SortedMap概述A{@linkMap}thatfurtherprovidesa<em>totalordering</em>onitskeys.Themapisorderedaccordingtothe{@linkplainComparablenaturalordering}ofitskeys,orbya{@linkComparator}typicallyprovidedatsortedmapcreati......
  • python ElementTree操作xml节点
    pythonElementTree操作xml节点,包括增删改查xml原文<Voucher><Id>967a198783d14835860574c697478156</Id><Remark>main摘要443344245567583384475</Remark><Delete>需要删除的节点1</Delete><DetailList><Det......
  • HashMap、TreeMap、Hashtable、HashSet和ConcurrentHashMap区别
    一、HashMap和TreeMap区别1、HashMap是基于散列表实现的,时间复杂度平均能达到O(1)。   TreeMap基于红黑树(一种自平衡二叉查找树)实现的,时间复杂度平均能达到O(logn)。2、HashMap、TreeMap都继承AbstractMap抽象类;TreeMap实现SortedMap接口,所以TreeMap是有序的!HashMap是无序的......
  • Springboot项目出现Error resolving template [index]的解决方法
    在SpringBoot中遇到模板文件不存在的问题在SpringBoot开发中,有时候会遇到Errorresolvingtemplate[index],templatemightnotexist这个错误,一般来说,这个错误可能有以下几种原因:模板文件路径错误:需要确认模板文件是否存在,并且其路径是否正确。通常模板文件的路径应该是class......
  • 无涯教程-批处理 - TREE函数
    此批处理命令以任意级别的递归或深度显示当前目录所有子目录的树。TREE-语法TreeTREE-示例@echoofftree上面的命令将显示当前目录的树结构,以下是输出示例。FolderPATHlistingforvolumeWindows8_OSVolumeserialnumberisE41C-6F43C:.├───newdir├─......
  • cf1446C. Xor Tree
    https://codeforces.com/problemset/problem/1446/C断断续续想了挺久的,还发现看错题了。首先一个显然的结论是不会成环,证明显然。突破口在于从高位往低位考虑,我们按照最高一位的值分成两类,一类是这一位为0,另一类为1,那么显然在我们不进行任何操作的时候,如果两个集合都不为空,那么......