HDU-1166-敵兵布陣(樹狀數組)
http://acm.hdu.edu.cn/showproblem.php?pid=1166
這題之前用線段樹做的,現在用樹狀數組
先簡單說下樹狀數組吧
如所示
c1 = a1
c2 = a1 + a2
c3 = a3
c4 = a1 + a2 + a3 + a4
c5 = a5
c6 = a5 + a6
c7 = a7
c8 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8
對於序列a,我們設一個數組C定義C[i] = a[i – 2^k + 1] + … + a[i],k為i在二進位下末尾0的個數
求2^k
int lowbit(int x){return x&(x^(x-1));}
將a[p]的值加上一個值x
void update(int p,int x){while(p<=n){c[p]+=x;p+=lowbit(p);}}
求前p項和
int sum(int p) {int sum=0;while(p>0){sum+=c[p]; p-=lowbit(p);}return sum;}
完整代碼
#include<stdio.h>#include<string.h>#include<stdlib.h>#define N 50005int a[N],c[N];int n;int lowbit(int x){return x&(x^(x-1));}void update(int p,int x){while(p<=n){c[p]+=x;p+=lowbit(p);}}int sum(int p) //前p相的和{int sum=0;while(p>0){sum+=c[p]; p-=lowbit(p);}return sum;}int main(){int t,i,m,k;int a1,a2;char str[10];scanf("%d",&t);for(k=1;k<=t;k++){scanf("%d",&n);memset(a,0,sizeof(a));memset(c,0,sizeof(c));for(i=1;i<=n;i++) //初值為0{scanf("%d",&m);a[i]+=m;update(i,m);}printf("Case %d:\n",k);while(scanf("%s",str),strcmp(str,"End")){if(strcmp(str,"Add")==0){scanf("%d%d",&a1,&a2);a[a1]+=a2;update(a1,a2);}else if(strcmp(str,"Sub")==0){scanf("%d%d",&a1,&a2);a[a1]-=a2;update(a1,-a2);}else if(strcmp(str,"Query")==0){scanf("%d%d",&a1,&a2);printf("%d\n",sum(a2)-sum(a1-1));}}}return 0;}