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

 

posted @ 2013-04-15 12:56  宛如  阅读(156)  评论(0编辑  收藏  举报