Binary-Index-Tree

注意!!!:这不是树状数组的详解,而是利用树状数组做区间修改的方法,当然能区间修改了也能单点修改

先来个简单的树状数组啊
功能:

  • 单点更新
  • 区间查询(单点查询也就是特殊的区间查询啦)
    int n;
    int a[100005];
    void add(int x,int id){//id的位置上的数加上x
        while(id<=n){
            a[id]+=x;
            id+=id&(-id);
        }
        return ;
    }
    int query(int id){//id位置的前缀和
        int ans=0;
        while(id){
            ans+=a[id];
            id-=id&(-id);
        }
        return ans;
    }

以前想区间更新的时候就要跑去写线段树了

但现在有了差分这种思想,就可以用树状数组去区间更新啦

我们对原数列 [ 1 , n ] [1,n] [1,n]进行一些操作啊
d i = a i a i 1 ( a 0 = 0 ) d_i=a_i -a_{i-1}(a_0=0) di=aiai1(a0=0)
那么
a x = <munderover> i = 1 x </munderover> d i a_x=\sum_{i=1}^x d_i ax=i=1xdi
又可得
<munderover> i = 1 x </munderover> a i = <munderover> i = 1 x </munderover> <munderover> j = 1 i </munderover> d j = <munderover> i = 1 x </munderover> ( x i + 1 ) d i \sum_{i=1}^x a_i=\sum_{i=1}^x\sum_{j=1}^i d_j=\sum_{i=1}^x (x-i+1)d_i i=1xai=i=1xj=1idj=i=1x(xi+1)di
显然(滑稽)
<munderover> i = 1 x </munderover> a i = ( x + 1 ) <munderover> i = 1 x </munderover> d i <munderover> i = 1 x </munderover> d i i \sum_{i=1}^x a_i=(x+1)\sum_{i=1}^x d_i - \sum_{i=1}^x d_i*i i=1xai=(x+1)i=1xdii=1xdii
也可以
<munderover> i = 1 x </munderover> a i = x × <munderover> i = 1 x </munderover> d i <munderover> i = 1 x </munderover> d i ( i 1 ) \sum_{i=1}^x a_i=x×\sum_{i=1}^x d_i - \sum_{i=1}^x d_i*(i-1) i=1xai=x×i=1xdii=1xdi(i1)

所以这种要维护两个数组,一个维护 d i d_i di和一个 d i d _i di * i i i
快点进正题啊,怎么区间修改啊,我等不及了
进正题,区间修改就用到差分的性质了,先来康康这个式子
a x = <munderover> i = 1 x </munderover> d i a_x=\sum_{i=1}^x d_i ax=i=1xdi
假设在区间 [ L , R ] [L,R] [L,R] n u m num num我们是不是只要在 d L d_L dL加上 n u m num num,在 R + 1 R+1 R+1上减去num.(没看懂的,自己想一下,很简单的啦)笔者出来挨锤
抛个板子,逃了逃了,怕挨锤

 struct BIT{
    long long a1[N],a2[N];
    int n;
    inline int lowbit(int x){
        return x&-x;
    }
    void init(int _n){
        n=_n+1;
        for(int i=0;i<=n;i++){
            a1[i]=0;
            a2[i]=0;
        }
    }
    void add(int x,int y){
        for(int i=x;i<=n;i+=lowbit(i)){
            a1[i]+=y;
            a2[i]+=1ll*x*y;
        }
    }
    void lradd(int l,int r,int x){
        add(l,x);
        add(r+1,-x);
    }
    long long sum(int x){
        long long ans=0;
        for(int i=x;i;i-=lowbit(i)){
            ans+=1ll*(x+1)*a1[i]-a2[i];
        }
        return ans;
    }
    long long lrsum(int l,int r){
        return sum(r)-sum(l-1);
    }
}bits;
全部评论

相关推荐

03-05 12:52
吉林大学 Java
挣K存W养DOG:他的价值在于把他家里积攒的财富回馈给社会
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务