树状数组相关算法

 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 }

 

posted @ 2017-04-20 21:12  Onthefly  阅读(265)  评论(0编辑  收藏  举报