树状数组区间更新

树状数组

(1)、单点增减+区间求和

思路:C[x]表示该点的元素:sum(x)=C[1]+C[2]+……C[x]

int arr[MAXN];

inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}

inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}

inline int query(int x,int y){return sum(y)-sum(x-1);}

 

(2)、区间增减+单点查询

思路:C[x]表示该点元素与左边元素的差值:num[x]=C[1]+C[2]+……C[x]

int arr[MAXN]

inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}

inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}

inline int update(int x,int y,int n){add(x,n);add(y+1,-n);}

 

//注意以上两种写法的ADD是一样的!!但是差分应用的地方不同,前者求和,后者修改!!

 

(3)、区间增减+区间查询

思路:C[x]表示该点元素与左边的差值

sum(sum(C[j],j<=i)i<=x)

= x*C[1]+(x-1)*C[2]+……+C[x]//关键思想

 =(x+1)*sum(C[i],i<=x)-sum(i*C[i],i<=x);

关键思想解释:x*C[1]是指1~X每个位都加上C[1],然后C[2]是与C[1]的差值,那么(x-1)*C[2]是指2~x每个位都加上C[2],当然可能是负值。先假定,再修正

 

则可以想到用C1[x]维护C[x]的值,C2[x]维护x*C[X]的值

template <typename X>

struct tree_array{

    struct tree_array_single{

        X arr[MAXN];

        void add(int x,X n){while(x<=N)arr[x]+=n,x+=lowbit(x);}

        X sum(int x){X sum=0;while(x)sum+=arr[x],x-=lowbit(x);return sum;}

    }T1,T2;

    void reset(){CLR(T1.arr,0); CLR(T2.arr,0);}

    void add(int x,X n){T1.add(x,n);T2.add(x,x*n);}

    void update(int L,int R,int n){add(L,n);add(R+1,-n);}

    X sum(int x){return (x+1)*T1.sum(x)-T2.sum(x);}

    X query(int L,int R){return sum(R)-sum(L-1);}

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值