树状数组:
管辖系统(暂且这么叫吧):
将数组里的数类似树一般管理起来,图片什么的网上可以找到一堆,按照图片来分析,仔细看会发现并不像二叉树之类的树一般整齐,而是树的树枝长度是参差不齐的,这是它使用类似二分实现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;
}