Logo handezheng 的博客

博客

树状数组

...
handezheng
2025-12-01 12:50:48
崖谷涂足无人问,山巅独饮众生哗。

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-03-16 10:33:48

树状数组


明确

树状数组仅能实现两个功能:

  1. 单点修改
  2. 区间查询

表示


如图,以 4 为例,二进制是100,它是010(2)和011(3)的父亲,是1000(8)的儿子
那么,对于c,它的父亲是二进制下,最后一个 1 (lowbit(c)) + 1

区间查询

令c[i]等于它管辖的数的和
以7为例,即111 求区间[1,7]就等于c[111] +c[110]+c[100]
下附模板:

int find(int u){
	int ans = 0;
	while(u){
		ans += c[u];
		u -= u&-u;\/\/去掉最后一个零
	}
	return ans;
}

求区间[l,r]即求[1,r] - [1,l - 1]

单点修改

注意:修改时应将其父亲,父亲的父亲...都修改
模板:

void add(int u,int x){\/\/将第u个数增加x
	while(u <= n){
		c[u] += x;
		u += u&-u;\/\/将最后一个零进一位
	}
}

谨记

相对于对于树状数组的两个功能,更重要的是将题意转化为树状数组能够实现的功能
树状数组2 的思路就是维护一个差分数组,将区间修改转化为两个区间端点的单点修改,将单点查询转化为查分数组的前缀和

好题

类似的树状数组题目还有 P1083 [NOIP2012 提高组] 借教室P1908 逆序对

P3372 【模板】线段树 1

特别的,对于 P3372 【模板】线段树 1 中的区间修改、区间求和问题:
我们可以维护两个树状数组,
第一个如树状数组2中的,是一个查分的树状数组,这样就实现了区间修改功能
而在查询时,现将查分树状数组进行前缀和,实现单点查询,再维护一个树状数组,用以前缀和第一个树状数组的前缀和,这样就实现了区间查询的功能

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。