树状数组进阶(区间修改+单点查询)

  这篇文章既然是进阶的文章,那么肯定需要一定的基础知识,所以,如果您对树状数组的基本原理和基本操作(区间查询和单点修改)不熟悉的话,请先看看我的另一片文章:树状数组趣解,因为有些基本的内容,我在这里就不会再提了。
  我们来看看本次要讲的内容和树状数组的基本职能有什么关系,一个是“区间修改+单点查询”,另一个是“区间查询+单点修改”,有什么发现?
  两者正好相反,所以我们也可以换一下思路,将两种操作的下标变换方向换一下,我先给出代码,再给原理。如果您善于思考,看一下就懂了,您也就不必再花时间看我的粗鄙的解释,当然了,如果您乐意,看看也无妨。


插一句:这里的思路其实是差分数组

代码

1、前几项值的修改

void change(int x,int p){//将1到x全加上p
	while(x>0){
		C[x]+=p;
		x-=lowbit(x);
	}
}

我们把这段代码和基本操作的点修改对比一下就能看出差距了,点修改是x+=lowbit(x)。

2、区间修改

void update(int l,int r,int p){//[l,r]上每个数加上p
	change(r,p);
	change(l-1,-p);
}

3、点查询

int query(int x){
	int ans=0;
	while(x<=n){
		ans+=C[x];
		x+=lowbit(x);
	}
	return ans;
}

原理

  下面是我讲解的时间了!这种操作应该怎么理解?我们从它的本质上去看。
  我们先来看看区间修改做了些什么。其实它只是将要加的值分配到对应的大结点,并不向小结点下放,比如:
又是这张熟悉的图
又是这张熟悉的图,比如我们要对1到8进行修改,那么它只会干一件事,那就是把C[8]修改然后就不再改动,因为8-lowbit(8)=0。
  那么,为什么可以这样做?这还得结合我们得点查询操作,毕竟我们这一步是为了单点查询服务的。所以我们来看看查询操作都干了些什么,很显然,它顺着它的父节点,把每个父节点的值都加了起来直到结束。那么我们还是来看上面这个例子,C[8]修改过后,1到8内的每一个位置在被查询的时候,总会加到C[8]这个父节点,这样就成功地把修改体现在查询中了。
  或者我们还能换个玄虚的解释,那就是把点当区间分解去修改,把区间合成就得到了点(查询)。放在这里供大家娱乐。

结束语

  挺简单的是吧?记得总结复习!

树状数组(Fenwick Tree)是一种用于高效处理区间修改单点查询数据结构。下面我将介绍如何使用树状数组实现区间修改单点查询。 首先,我们需要定义树状数组数据结构树状数组由一个数组和一组操作组成,其中数组用于存储数据,操作用于更新和查询数组中的值。 下面是一个示例的树状数组实现: ```python class FenwickTree: def __init__(self, n): self.size = n self.tree = [0] * (n + 1) def update(self, idx, delta): while idx <= self.size: self.tree[idx] += delta idx += idx & -idx def query(self, idx): res = 0 while idx > 0: res += self.tree[idx] idx -= idx & -idx return res def range_update(self, l, r, delta): self.update(l, delta) self.update(r + 1, -delta) def point_query(self, idx): return self.query(idx) ``` 在上面的代码中,我们定义了一个FenwickTree类,通过构造函数`__init__`来初始化树状数组,并使用`size`来表示数组的大小。`tree`数组用于存储数据。`update`方法用于更新指定位置的值,`query`方法用于查询指定位置之前的求和结果。`range_update`方法用于对指定区间进行修改,`point_query`方法用于查询单个位置的值。 下面是一个示例的使用场景: ```python # 示例使用 n = 10 tree = FenwickTree(n) # 区间修改 [2, 6] 的值加 3 tree.range_update(2, 6, 3) # 查询位置 5 的值 value = tree.point_query(5) print(value) ``` 在上面的示例中,我们创建了一个大小为10的树状数组,并对区间[2, 6]的值进行了修改,将其加3。然后,我们查询了位置5的值,结果为3。 希望以上内容能够帮助到你实现树状数组区间修改单点查询。如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值