树状数组(一)

版权声明:蒟蒻写博客不宜,请随文附上原文链接 https://blog.csdn.net/qq_34493840/article/details/84976158

树状数组定义

树状数组数组顾名思义它是树状的数组
百度:树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。

树状数组常用操作

一、神奇的lowbit

树状数组图

假设数组a[1…n],那么查询a[1]+…+a[n]的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别。
来观察这个图:
令这棵树的结点编号为C1,C2…Cn。令每个结点的值为这棵树的值的总和,那么容易发现:
C1 = A1
C2 = A1 + A2
C3 = A3
C4 = A1 + A2 + A3 + A4
C5 = A5
C6 = A5 + A6
C7 = A7
C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8

C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16

那么就有了一个有趣的性质

设节点编号为x,那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素。因为这个区间最后一个元素必然为Ax,
所以很明显:Cn = A(n – 2^k + 1) + … + An

那么lowbit操作就显而易见了

inline int lowbit(int k) {
	return k & -k;
}

二、单点修改

由于在树状数组中改变一个点会牵动所有管辖他的店那么在修改时就需要lowbit了

inline void add(int x, int k) { //x要修改的那个数, k为要加的值
	while(x <= n) {
		c[x] += k;
		x += lowbit(x);
	}
}

三、求和操作

inline int ask(int k) {
	int ans = 0;
	while(k) {
		ans += s[k];
		k -= lowbit(k);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_34493840/article/details/84976158