树状数组(二)【区间修改,单点查询】

【区间修改,单点查询】

区间修改
考虑一个数组,频繁的进行区间(l~r)修改,这时候我们会利用差分数组,(关于差分数组 ) 因为只需要修改 l 和r+1就可以,复杂度O(1),最后求个前缀和即可。树状数组进行区间修改也一样可以用差分数组来实现。
我们维护一个差分数组,这个差分数组不需要是原数组的差分数组,可以当做是当前变化量的差分数组。显然在初始阶段,没有对任何区间做任何操作,所以这个差分数组全部是0。这样也是方便单点查询,因为这个差分数组的前缀和就是当前值的变化量。
举个例子:

   原数组a:      4  1  2  5  6
变化量的差分数组t:0  0  0  0  0  (刚开始都是0)
下面对原数组第2~4个元素+2
变化量的差分数组t:0  2  0  0  -2 
差分数组前缀和t:  0  2  2  2  0
可以发现求完前缀和正好是进行的修改操作。
如果要求某一个位置现在的值,只需要a[i]+t[i]

所以我们维护这个差分数组就好,区间修改其实也就修改两个点,所以操作就是单点修改的操作。
因为初始的差分数组全是0,所以还不用建树了。

单点查询
根据上面的例子,首先求前缀和,这也是个基本操作,区间查询里也用到过,之后与原数组的那个点相加就是最后结果。

实现也比较简单。
洛谷模板题:树状数组2
代码:

#include <bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(int i=a;i<b;i++)
#define lowbit(x) ((x)&(-x))
typedef long long ll;

const int MXN = 5e5+5;
int a[MXN],t[MXN];  //a是原数组。t是差分数组,用树状数组维护。
int n,m;
void update(int l,int r,int x)  //区间修改,l~r变化了x
{
    while(l<=n){        //t[l]+x
        t[l]+=x;
        l+=lowbit(l);
    }
    r++;                //t[r+1]-x
    while(r<=n){
        t[r]-=x;
        r+=lowbit(r);
    }
}
int getsum(int k)       //求差分数组前缀和
{
    int sum=0;
    while(k>0){
        sum+=t[k];
        k-=lowbit(k);
    }
    return sum;
}
int main()
{
    scanf("%d %d",&n,&m);
    rep(i,1,n+1) scanf("%d",&a[i]);
    int p,l,r,x,k;
    rep(i,0,m){
        scanf("%d",&p);
        if(p==1){
            scanf("%d %d %d",&l,&r,&x);
            update(l,r,x);
        }
        else{
            scanf("%d",&k);
            printf("%d\n",a[k]+getsum(k));  //求某点的值
        }
    }
    return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
树状数组(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、付费专栏及课程。

余额充值