這是看劉汝佳的那本白書寫的代碼,關於樹狀數組一些簡單的操作查詢區間和和更新值某點值。
查詢只是返回從1到第i個元素的和,還不是任意的區間(l,r)。不過用r的結果減去l-1的結果就可以求得任意(l,r)的區間和。
更新也只是將第i個元素加某一值,減法做法也類似。
下面是代碼:
#include<cstdio>
#include<cstdlib>
#include<cstring>
int n;
int c[100];
//c數組為待處理的數組a中的一段連續和
//ci為在左邊最靠近原數組中第i個元素的祖先的後一個到第i個自身所有元素之和
int lowbit(int x)
{
return x&(-x); //計算第x位的lowbit,
}
int sum(int k) //calculate the sum of first k element
{
int s=0;
while(k>0)
{
s+=c[k];
k-=lowbit(k);
//不斷向左邊去找最近的祖先,直到找到root或左邊無祖先,k為c數組的下標
}
return s;
}
void update_add(int add_num,int k) //add add_num to the k's element
{
while(k<=n)
{
c[k]+=add_num;
k+=lowbit(k);
//不斷向右邊去找最近的祖先,直到找到root或右邊無祖先,k為c數組之下標
//不斷將c數組中包含第k元素的節點加值
}
}
int main()
{
freopen("in.txt","r",stdin);
int a[100];
int i,j,m;
while(scanf("%d",&n)==1 && n!=0)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);//讀入原數組a
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
{
j=i-lowbit(i)+1;
for(int u=j;u<=i;u++)
c[i]+=a[u];
//建構c數組
}
for(i=1;i<=n;i++)
printf("%d\n",c[i]);
//============================================================================
//以下為測試樹狀數組add(x,d)和query(1,r)是否成功,輸入m個指令,每條一行
//若指令為a開頭,後面跟兩個數字d和x,則為將原數組a的第x個元素加d
//若為s開頭,後面跟一個數字k,則為查詢數組a中1到k之和
scanf("%d",&m); //input m operations
char ch=getchar();
char cc[4];
while(m--)
{
gets(cc);
if(cc[0]=='a') // if the first alphabet is a,the operation is add a number to k's element,such as a35
{update_add(cc[1]-'0',cc[2]-'0');
for(i=1;i<=n;i++)
printf("%d ",c[i]);
printf("=====\n");
}
else printf("%d\n",sum(cc[1]-'0'));// otherwise query the sum of first k elements,such as s6
}
}
return 0;
}