码迷,mamicode.com
首页 > 编程语言 > 详细

树状数组

时间:2017-11-08 13:08:09      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:href   strong   sha   blank   com   highlight   add   +=   一段   

转载自EdwardFrog‘s Home

 

奇妙的数据结构。

  常用于 单点修改、区间查询。也可以通过某些手段进行 区间修改、单点查询

  本篇主要讨论后者。

——————————————————————————————————————————————————————————————————————

讨论之前,先上一下单点修改、区间查询的代码:

 struct Node {
	int tree[MAXN];
	void add(int x, int v) {
		while (x <= n) {
			tree[x] += v;
			x += x&(-x);
		}
	}
	int sum(int k) {
		int ans = 0;
		while (k) {
			ans += tree[k];
			k -= k & (-k);
		}
		return ans;
	}
} T;

————准备材料———————————————————————————————————————————————————————————

  原数组a,和它的差分数组 C 。

————制作过程———————————————————————————————————————————————————————————

区间修改

  树状数组的修改并没有真正修改原数组的数,只是利用各种玄学得到修改后的那个结果 。

  a[ n ] = c[ 1 ] + c[ 2 ] + ... + c[ n ]     (不懂的话,自己举个例子试试)

  对a中的某一段连续的区间[l,r]进行修改时,c数组中只有c[l]和c[r + 1]改变。
  也就是说,要进行对[l, r]的修改,实际上改变c[l],c[r + 1]两个值即可。  

区间修改[l,r]+=v:

add(c[l],v),add(c[r+1],-v);        add(c2[l],(l-1)v),add(c2[r+1],-rv);

 

区间查询

  考虑普通做法中,维护一个前缀和数组sum。求[l, r]一段的区间和只要求 sum[r] - sum[l - 1] 即可,推一推可以知道

 

1 sum[n] = a[1] + a[2] + ... + a[n]
2     = c[1] + (c[1] + c[2]) + ... + (c[1] + c[2] + ... + c[n])
3     = n * (c[1] + ... + c[n]) - (0 * c[1] + 1 * c[2] + ... + (n - 1)*c[n])

  现在问题就变成了求 (c[1] + ... + c[n]) 和 (0 * c[1] + 1 * c[2] + ... + (n - 1)*c[n]) 。

  再开一个数组 c2,c2[ i ] = c[ i ] *(i - 1)。

 

求前缀和sum(1,n):

sum(1,n)=n*query_c(n)-query_c2(n).

求区间和sum(l,r):

sum(l,r)=sum(r)-sum(l-1).

树状数组

标签:href   strong   sha   blank   com   highlight   add   +=   一段   

原文地址:http://www.cnblogs.com/ExileValley/p/7803290.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!