树状数组相关算法
1 #define N 100005 2 3 //算法1:取最低位1 4 #define lowbit(a) (a&-a) 5 6 //算法2:获取树状数组下标i元素表示区间的左端点下标 7 #define left(i) (i-lowbit(i)+1) 8 9 //算法3:获取树状数组元素i的父元素下标 10 #define parent(i) (i+lowbit(i)) 11 12 int n,sum[N]; 13 14 //算法4:由数组a建立树状数组b 15 void build(int a[],int b[]) 16 { 17 int i; 18 sum[0]=0; 19 for(i=1;i<=n;i++) 20 sum[i]=sum[i-1]+a[i]; 21 for(i=1;i<=n;i++) 22 b[i]=sum[i]-sum[left(i)-1]; 23 } 24 25 //算法5:由数组a建立差分数组d 26 void delta(int a[],int d[]) 27 { 28 int i; 29 a[0]=0; 30 for(i=1;i<=n;i++) 31 d[i]=a[i]-a[i-1]; 32 } 33 34 //算法6:由差分数组d建立等差乘差分数组di 35 void deltai(int d[],int di[]) 36 { 37 int i; 38 for(i=1;i<=n;i++) 39 di[i]=i*d[i]; 40 } 41 42 //算法7:在树状数组t中单点查询 43 int value(int t[],int index) 44 { 45 int ans=t[index]; 46 for(int i=index-1;left(i)>=left(index);i=left(i)-1) 47 ans-=t[i]; 48 return ans; 49 } 50 51 //算法8:在树状数组t中查询 k-前缀和 52 int ksum(int t[],int k) 53 { 54 int ans=0; 55 for(int i=k;i>0;i=left(i)-1) 56 ans+=t[i]; 57 return ans; 58 } 59 60 //算法9:在树状数组t中查询[l,r]区间和 61 int lrsum(int t[],int l,int r) 62 { 63 return ksum(t,r)-ksum(t,l-1); 64 } 65 66 //算法10:在差分树状数组td与tdi中查询 k-前缀和 67 int dksum(int td[],int tdi[],int k) 68 { 69 return (k+1)*ksum(td,k)-ksum(tdi,k); 70 } 71 72 //算法11:在差分树状数组td与tdi中查询[l,r]区间和 73 int dlrsum(int td[],int tdi[],int l,int r) 74 { 75 return dksum(td,tdi,r)-dksum(td,tdi,l-1); 76 } 77 78 //算法12:在树状数组t中单点修改 79 void kadd(int t[],int k,int d) 80 { 81 for(int i=k;i<=n;i=parent(i)) 82 t[i]+=d; 83 } 84 85 //算法13:在差分树状数组td与tdi中区间修改 86 void lradd(int td[],int tdi[],int l,int r,int d) 87 { 88 kadd(td,l,d); 89 kadd(td,r+1,-d); 90 kadd(tdi,l,l*d); 91 kadd(tdi,r+1,-(r+1)*d); 92 }