`
java-mans
  • 浏览: 11389851 次
文章分类
社区版块
存档分类
最新评论

HDU-1166-敌兵布阵(树状数组)

 
阅读更多

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 50005
int 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;
}







分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics