James Bryant

【转】关于树状数组的模板

0
阅读(1133)

树状数组在只是单点添加和区间求和的过程中实用效率远大于线段树,所以有必要学习一下(个人见解)

lowbit:i&(-i)

对于单点添加直接使用add就可以完成,如果还有别的操作还可以再另写函数。

对于求和可以直接用 summax  减去  summin-1 就可以求出区间和比、代码复杂度远低于线段树。

以洛谷3374为例:http://daniu.luogu.org/problem/show?pid=3374#sub

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<string>
 4 using namespace std;
 5 #define MAX 500000
 6 int N,M;
 7 int a[MAX],c[MAX];
 8 //======================================================
 9 void init();//
10 void ADD(int ,int );//
11 int sum(int );
12 //======================================================
13 void ADD(int x,int y)
14 {
15    for(int i=x;i<=N;i+=i&(-i)  ){
16       c[i]+=y;
17    }
18 }
19 //======================================================
20 int sum(int x)
21 {
22    int SUM=0;
23    for(int i=x;i>=1;i-=i&(-i))
24       SUM+=c[i];
25    return SUM;
26 }
27 //======================================================
28 void init()
29 {
30    int aa,bb,cc;
31    cin>>N>>M;
32    for(int i=1;i<=N;i++){
33       cin>>a[i];
34       ADD( i , a[i] );
35    }
36    for(int i=1;i<=M;i++){
37       cin>>aa>>bb>>cc;
38       if(aa==1)ADD(bb,cc);
39       if(aa==2)cout<<sum(cc)-sum(bb-1)<<endl;
40    }
41 }
42 //======================================================
43 int main()
44 {
45   init();
46    return 0 ;
47 }