树状数组:
管辖系统(暂且这么叫吧):
将数组里的数类似树一般管理起来,图片什么的网上可以找到一堆,按照图片来分析,仔细看会发现并不像二叉树之类的树一般整齐,而是树的树枝长度是参差不齐的,这是它使用类似二分实现log复杂度的性质所决定的,每个位置所管辖的区域都是自己二进制表示时 最右边的1 表示的大小 的长度,例如 7(十进制)=111(二进制),他管辖范围是1(二进制),也就是他本身,6(十进制)=110(二进制),他管下的范围是10(二进制)=2(十进制),也就是管辖长度为2,他所管辖的位置是5,6。树状数组中每一项的值也就是原数列中其管辖范围内的和。求管辖范围的操作也就是其核心 lowbit 。
int lowbit(int i)
{
return i&(-i);
}
区间求和:
树状数组基本操作,假如要求前i项和,我们首先直接加上该位置所管辖的范围,即该位置的值。接着加他所管不到的范围即 i - lowbit(i)位置的值(为什么是 i - lowbit(i),假如1—6区间和,你已经加上了6 管辖部分(长度为2)的和,这个时候当然要去计算1–4区间的和,4 = 6 - 2 )一直递归求和加完即可。l,r 区间求和即前 r 项和减前 l - 1 项和
int sum(int x)
{
int tmp=0;
while(x)
{
tmp+=t[x];
x-=lowbit(x);
}
return tmp;
}
单点修改:
基本操作 。要改某一位置的值,必须得同时改管辖它的值,否则求和操作就会出现问题。怎么找离他最近的管辖它的值,使用 i + lowbit(i)(以 i=1010000(二进制)举例,要想管住它,肯定要是比它大的数,设为s, 则 s - lowbit(s)< i 若选择了 s=1011xxx,即使最好的情况下 即 1011000 管辖的范围最远也无法涉及它

本文详细介绍了树状数组的概念及其在区间求和、单点修改、区间修改和单点修改区间最大值查询中的应用。树状数组通过管辖系统管理数组元素,每个位置管辖的区域与其二进制表示的最右边1对应的长度相关。区间求和通过递归累加管辖范围内的值,单点修改需要更新所有管辖该位置的值。对于区间修改,可以采用额外的lz数组进行标记。单点修改区间最大值查询则需要枚举影响的父亲节点。虽然树状数组在某些问题上操作相对复杂,但它在时间和空间上有其优势。
最低0.47元/天 解锁文章

879

被折叠的 条评论
为什么被折叠?



