HDU-1166-敌兵布阵(树状数组,附解释)

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

http://acm.hdu.edu.cn/showproblem.php?pid=1166


初学树状数组,,  
题目大意:更新点查区间,,
简单介绍一下树状数组,看下图。

HDU-1166-敌兵布阵(树状数组,附解释)_第1张图片


c1 = a1

c3 = a3

c4 = a1 + a2 + a3 + a4

c5 = a5

c6 = a5 + a6

c7 = a7

c8 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8

c9=a9
c10=a9+a10


对于序列a,我们设一个数组C定义C[i] = a[i – 2^k + 1] + … + a[i],k为i在二进制下末尾0的个数

求2^k

求x在二进制下末尾0的个数(第一个一出现的位置)

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
#include
#define lowbit(x) (x&(x^(x-1)))
#define maxn 50010
using namespace std;
int c[maxn];
int n;
void update(int p,int x)///给 a[p] 加上 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,t=0;
    char str[10];
    scanf("%d",&T);
    while(T--)
    {
        int x,y;
        scanf("%d",&n);
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            update(i,x);
        }
        printf("Case %d:\n",++t);
        while(scanf("%s",str)&&str[0]!='E'){
            scanf("%d %d",&x,&y);
            if(str[0]=='A')
                update(x,y);
            else if(str[0]=='S')
                update(x,-y);
            else if(str[0]=='Q'){
                printf("%d\n",sum(y)-sum(x-1));
            }
        }
    }
    return 0;
}

参考文章:http://blog.csdn.net/cambridgeacm/article/details/7771782


你可能感兴趣的:(acm_树状数组)