hdu1166树状数组
树状数组的应用一:单点更新,区间求和
http://baike.baidu.com/view/1420784.htm
设节点编号为x,
那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素
int Lowbit(x)
{
return x&(-x);
}
如:
x =1: 1 &-1(设位数为8)0000 0001 & 1111 1111 = 1
x = 6:6 & -6 0000 0110
&1111 1010 = 2
总结一下,其实就是:
求出2^k(其中k: x 的二进制表示数中, 右向左数第一个1的位置),
如6的二进制表示为110,向左数第零个为0,第一个为1,
则k=1,故Lowbit(6) = 2^1 = 2。
这题也可以用线段树
#include<stdio.h> #include<string.h> int N,c[50009],a[50009]; char mingli[10]; int lowbit(int x) { return x&(-x); } void modify(int n,int value) { while(n<=N) { c[n]=c[n]+value; n=n+lowbit(n);//就是得到的改点的父节点的值 } } int sum(int n) { int sum=0; while(n>0) { sum=sum+c[n]; n=n-lowbit(n);//就是得到x这个点的管辖区间的下个区间的管辖点 } return sum; } int query(int i,int j) { return sum(j)-sum(i-1); } int main() { int t,i,j,k; scanf("%d",&t); for(i=1;i<=t;i++) { printf("Case %d:\n",i); scanf("%d",&N); memset(a,0,sizeof(a)); memset(c,0,sizeof(c)); for(j=1;j<=N;j++) { scanf("%d",&a[j]); modify(j,a[j]); } while(scanf("%s",&mingli)&&strcmp(mingli,"End")!=0) { scanf("%d%d",&j,&k); if(strcmp(mingli,"Add")==0) modify(j,k); else if(strcmp(mingli,"Sub")==0) modify(j,-k); else if(strcmp(mingli,"Query")==0) printf("%d\n",query(j,k)); } } }