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));
}
}
}

浙公网安备 33010602011771号