树状数组可以说是一种特殊的线段树,他们有共同的点,BIT通过lowbit来控制线段的长度,可以用于单点修改区间查询,单点查询区间修改,逆序对等等。这里介绍这三种方法来简单描述一下。


 

  一:单点修改区间查询

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e6+10;
 4 int n,m;
 5 int a[maxn],tr[maxn];
 6 int lowbit(int x){return x& -x;}
 7 void add(int point,int dig)    {for(int i=point;i<=n;i+=lowbit(i))    tr[i]+=dig;}
 8 int ask(int x)
 9 {
10     int ans=0;
11     for(int i=x;i>0;i-=lowbit(i))    ans+=tr[i];
12     return ans;
13 }
14 int main()
15 {
16     memset(tr,0,sizeof(tr));
17     scanf("%d%d",&n,&m);
18     for(int i=1;i<=n;i++)    scanf("%d",&a[i]);
19     for(int i=1;i<=n;i++)    add(i,a[i]);
20     while(m--)
21     {
22         int op;    scanf("%d",&op);
23         if(op==1){
24             int x,k;    scanf("%d%d",&x,&k);
25             add(x,k);
26         }
27         else{
28             int x,y;    scanf("%d%d",&x,&y);
29             printf("%d\n",ask(y)-ask(x-1));
30         }
31     }
32     return 0;
33  }

二:单点查询区间修改。(思想在于用前缀和来处理)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn = 5e5+10;
 5 int n,m;
 6 LL a[maxn],b[maxn],tr[maxn];
 7 LL lowbit(LL x){return x & -x;}
 8 void add(int point,LL dig)    {for(int i=point;i<=n;i+=lowbit(i))    tr[i]+=dig;}
 9 LL ask(int x){
10     LL ans=0;
11     for(int i=x;i>0;i-=lowbit(i))    ans+=tr[i];
12     return ans;
13 }
14 int main()
15 {
16     memset(a,0,sizeof(a));
17     memset(b,0,sizeof(b));
18     scanf("%d%d",&n,&m);
19     for(int i=1;i<=n;i++){
20         LL temp;    scanf("%lld",&a[i]);
21         b[i]=a[i]-a[i-1];
22         add(i,b[i]);
23     }
24     while(m--)
25     {
26         int op;    scanf("%d",&op);
27         if(op==1)
28         {
29             int x,y;    LL k;    scanf("%d%d%lld",&x,&y,&k);
30             add(x,k);    add(y+1,-k);
31         }
32         else{
33             int x;    scanf("%d",&x);
34             printf("%lld\n",ask(x));
35         }
36     }
37     return 0;
38 }

三:逆序对。(Focus on this problem's digit!!)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 5e5+10;
 4 typedef long long LL;
 5 int n,b[maxn];LL tr[maxn];
 6 struct point{
 7     int val,num;
 8 }a[maxn];
 9 inline LL read()
10 {
11     int op=1;LL x=0;
12     char ch=getchar();
13     while(!isdigit(ch)){if(ch=='-')    op=-1;    ch=getchar();}
14     while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';    ch=getchar();}
15     return op*x;
16 }
17 bool cmp(point x,point y)
18 {
19     if(x.val==y.val)    return x.num<y.num;
20     return x.val<y.val;
21 }
22 LL lowbit(int x){return x&(-x);}
23 void add(int p,int dig){for(;p<=n;p+=lowbit(p))    tr[p]+=dig;}
24 LL ask(int p)
25 {
26     LL res=0;
27     for(;p>0;p-=lowbit(p))    res+=tr[p];
28     return res;
29 }
30 int main()
31 {
32     memset(tr,0,sizeof(tr));
33     n=read();
34     for(int i=1;i<=n;i++){
35         a[i].val=read();
36         a[i].num=i;
37     }
38     sort(a+1,a+n+1,cmp);
39 //    for(int i=1;i<=n;i++)    cout<<a[i].num<<" "<<a[i].val<<'\n';
40     for(int i=1;i<=n;i++)    b[a[i].num]=i;
41     LL ans=0;
42     for(int i=1;i<=n;i++)
43     {
44         add(b[i],1);
45         ans+=i-ask(b[i]);
46     }
47     printf("%lld",ans);
48     return 0;
49 }

BIT的用法当然还有很多,它主要把区间的o(N)降低为o(logN)。