树状数组

参考链接:https://www.cnblogs.com/Glacier-elk/p/9284523.html

     https://blog.csdn.net/qq_40970841/article/details/81297414

如题,已知一个数列,你需要进行下面两种操作(点更新):

1.将某一个数加上x

2.求出某区间每一个数的和

#include<iostream>
#define MAXN 2000010
using namespace std;
int n,m,a;
int q,x,y;
int e[MAXN];//树状数组,树状数组index是从1开始的
int lb(int o){ //lowbit
    return o&(-o);
}
void addto(int x,int v){
    while(x<=n){
        e[x]+=v;
        x+=lb(x);
    }
}
int query(int x){
    int ans=0;//因为e[i]中有a[i],所以ans从0开始加
    while(x>0){
        ans+=e[x];
        x-=lb(x);
    }
    return ans;
}
int main(){
    int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++){
        scanf("%d",&a);
        addto(i,a); //这里与模板2不同,需要先把初值加入树状数组
    }
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&q,&x,&y);
        if(q==1) addto(x,y);
        else printf("%d
",query(y)-query(x-1));
    }
    return 0;
}

如题,已知一个数列,你需要进行下面两种操作(区间更新):

1.将某区间每一个数数加上x

2.求出某一个数的值

#include<iostream>
using namespace std;
int m,n,x,y,k,q;
int a[500010],e[500010];//a[i]是初值,e[i]是累加值(不包含初值)
int lb(int o){ //返回o所在区间的长度
    return o&(-o);
}
void addto(int x,int k){ //给树状数组x之前的值+k
    while(x>0){
        e[x]+=k;
        x-=lb(x);
    }
}
int query(int x){
    int ans=a[x]; //因为e[i]不包含初值,先把初值加进来
    while(x<=n){
        ans+=e[x];
        x+=lb(x);
    }
    return ans;
}
int main(){
    int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++) scanf("%d",&a[i]);
    for(i=1;i<=m;i++){
        scanf("%d",&q);
        if(q==1){
            scanf("%d%d%d",&x,&y,&k);
            addto(y,k);
            addto(x-1,-k);//先把y之前的+k,再把x-1之前的-k---->给[x,y]+k
        }
        else{
            scanf("%d",&x);
            printf("%d
",query(x));
        }
    }
    return 0;
}
加油啦!加油鸭,冲鸭!!!
原文地址:https://www.cnblogs.com/clarencezzh/p/10413540.html