(1)用树状数组更新区间,进行单点查询
总体思路:树状数组对应的数组A是一个差分数组,利用树状组数进行单间查询只需要logn的复杂度。
例题:题目链接
Color the ball
N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗?

Input
每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N)。
当N = 0,输入结束。

Output
每个测试实例输出一行,包括N个整数,第I个数代表第I个气球总共被涂色的次数。

Sample Input
3
1 1
2 2
3 3
3
1 1
1 2
1 3
0

Sample Output
1 1 1
3 2 1

#include<iostream>
#include<cstring>
using namespace std;
int n;
int a[100005];
int c[100005];
int lowbit(int i){
    return i&-i;
}
void add(int i,int x){
    while(i<=n){
        c[i]+=x;
        i+=lowbit(i); 
    }
    return ;
}
int sum(int i){
    int s=0;
    while(i>0){
        s+=c[i];
        i-=lowbit(i);
    }
    return s;
}
int main(){
    while(1){
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        scanf("%d",&n);
        if(n==0) break;
        int x,y;
        for(int i=1;i<=n;i++){
            scanf("%d %d",&x,&y);
            add(x,1);
            add(y+1,-1);
        }
        for(int i=1;i<=n;i++){
            int ans=sum(i);
            if(i==1) printf("%d",ans);
            else printf(" %d",ans);
        }
        printf("\n");
    }
    return 0;
}

2、单点更新,区间查询
题目链接
题目大意:
第一行一个整数T,表示有T组数据。
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令

Output
对第i组数据,首先输出“Case i:”和回车,
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。

#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int t;
int n;
int a[50005];
int c[50005];
int lowerbit(int x){
    return x&(-x);
}
void add(int i,int x){
    while(i<=n){
        c[i]+=x;
        i+=lowerbit(i);
    }
    return ;
}
int sum(int i){
    int sum=0;
    while(i>0){
        sum+=c[i];
        i-=lowerbit(i);
    }
    return sum;
}
int main(){
    scanf("%d",&t);
    for(int k=1;k<=t;k++){
        cout<<"Case "<<k<<":\n";
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            add(i,a[i]);
        }
        string x;
        while(1){
            cin>>x;
            if(x=="End") break;
            int t1,t2;
            scanf("%d %d",&t1,&t2);
            if(x=="Query"){
                int ans=sum(t2)-sum(t1-1);
                printf("%d\n",ans);
            }
            if(x=="Add"){
                add(t1,t2);
            }
            if(x=="Sub"){
                t2=t2*-1;
                add(t1,t2);
            }
        }
    }
    return 0;
} 

3、树状数组主要是方便,代码简洁,在更新区间,查询区间时已经失去了他的优势,所以我们一般用线段树不用树状数组。