树状数组
引例:1. 给出任意n个元素,请计算前K(k<=n)项的和。
2. 现随机改变第m(m <= n)项的值,请计算前K(k<=n)项的和。
这就是我们今天要讨论的树状数组的问题。要解决引例中的问题,最简单也是最暴力的做法就是,每修改一次值就重新计算一次和,总共计算n次;根据经验可知,修改第m项数据,则m项之前的数据和是不变的,改变的只是包含于第m项的区间和。所以我们想能不能减少求和次数呢?
|
C[1] = A[1];
C[2] = A[1] + A[2];
C[3] = A[3];
C[4] = A[1] + A[2] + A[3] + A[4];
C[5] = A[5];
C[6] = A[5] + A[6];
C[7] = A[7];
C[8] = A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8];
规则如下:
C
[
i
]
=
A
[
i
−
2
k
+
1
]
+
A
[
i
−
2
k
+
2
]
+
.
.
.
+
A
[
i
]
;
\ C[i] = A[i-2^{k}+1]+A[i-2^{k}+2]+...+A[i];
C[i]=A[i−2k+1]+A[i−2k+2]+...+A[i];
其
中
,
k
为
i
的
二
进
制
中
从
最
低
位
到
高
位
连
续
零
的
长
度
,
也
就
是
第
一
位
1
出
现
的
位
置
,
例
如
i
=
8
(
1000
)
时
候
,
k
=
3.
\ 其中,k为i的二进制中从最低位到高位连续零的长度,也就是第一位1出现的位置,例如i = 8(1000)时候,k = 3.
其中,k为i的二进制中从最低位到高位连续零的长度,也就是第一位1出现的位置,例如i=8(1000)时候,k=3.
下面给出各项和的通项公式:
S
u
m
i
=
C
[
i
]
+
C
[
i
−
2
k
1
]
+
C
[
i
−
2
k
1
−
2
k
2
]
+
.
.
.
其
中
k
1
=
0
,
k
2
=
1...
\ Sum_{i} = C[i]+C[i-2^{k_{1}}]+C[i-2^{k_{1}}-2^{k_{2}}]+... 其中k1=0,k2=1...
Sumi=C[i]+C[i−2k1]+C[i−2k1−2k2]+...其中k1=0,k2=1...
例如求前7项和,
S
u
m
7
=
C
[
7
]
+
C
[
6
]
+
C
[
4
]
,
根
据
图
表
所
示
,
是
正
确
的
.
\ Sum_{7} = C[7]+C[6]+C[4],根据图表所示,是正确的.
Sum7=C[7]+C[6]+C[4],根据图表所示,是正确的.
有
了
这
个
关
系
式
,
我
们
便
可
以
以
更
快
的
速
度
求
出
任
意
项
和
,
但
是
还
是
有
难
度
的
。
\ 有了这个关系式,我们便可以以更快的速度求出任意项和,但是还是有难度的。
有了这个关系式,我们便可以以更快的速度求出任意项和,但是还是有难度的。
首
先
是
2
k
问
题
,
我
们
先
给
出
结
论
:
2
k
=
i
&
(
−
i
)
\ 首先是 2^{k}问题,我们先给出结论 :2^{k}=i \&(-i)
首先是2k问题,我们先给出结论:2k=i&(−i)
这是因为负数是以补码存储的,对于整数运算 x&(-x)
有当x为0时,即 0 & 0,结果为0;
当x为奇数时,最后一个比特位为1,取反加1没有进位,故x和-x除最后一位外前面的位正好相反,按位与结果为0。结果为1。
当x为偶数,且为2的m次方时,x的二进制表示中只有一位是1(从右往左的第m+1位),其右边有m位0,故x取反加1后,从右到左第有m个0,第m+1位及其左边全是1。这样,x& (-x) 得到的就是x。
当x为偶数,却不为2的m次方的形式时,可以写作
x
=
y
×
2
k
\ x=y\times 2^{k}
x=y×2k,其中,y的最低位为1。
对于该运算我们称之为lowbit,即取上述中的
2
k
\ 2^{k}
2k.
示例代码
int n;//项个数
int a[2019],c[2019]; //对应原数组和树状数组
//求2^k,x为第几项
int lowbit(int x){
return x&(-x);
}
//由于原数组的i位+k,而引起有关节点的改变
void updata(int i,int k){
while(i <= n){
c[i] += k;
i += lowbit(i);
}
}
//求第1项到第i项的和
int getsum(int i){
int res = 0;
while(i > 0){
res += c[i];
i -= lowbit(i);
}
return res;
}
上面的三个函数是核心,改造之后可以实现随机查询、区间求和等问题,需要铭记于心。——The End——