树状数组(模板)

转载请注明出处:http://blog.csdn.net/u012860063

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


题目分析

将一组数组a[N]

输入Query a b,输出SUM(ai + …… + aj)

输入Add i j,s[i] = s[i] + j

输入Sub  i j,s[j] = s[i] -  j

数组动态求和,明显的树状数组,调用树状数组模版:树状数组


一,每次修改的是一个点,所求的是关于某段区间;


直接贴模板:

#include <cstdio>  
#include <cstring>  
#define maxn 50047  
int c[maxn], a[maxn]; 
int n,t;
int Lowbit(int x)  // 2^k
{
	return x&(-x);
}
void update(int i, int x)//i点增量为x
{
	while(i <= n)
	{
		c[i] += x;
		i += Lowbit(i);
	}
}
int sum(int x)//区间求和 [1,x]
{
	int sum=0;
	while(x>0)
	{
		sum+=c[x];
		x-=Lowbit(x);
	}
	return sum;
}
  
int Getsum(int x1,int x2) //求任意区间和
{ 
    return sum(x2) - sum(x1-1); 
}  
int main() 
{ 
	int i , j;
    scanf("%d",&t); 
    int count = 0; 
    while(t--) 
    { 
        count++; 
        memset(a,0,sizeof(a)); 
        memset(c,0,sizeof(c)); 
        scanf("%d",&n); 
        for(i = 1; i <= n; i++) //i须从1开始
        { 
            scanf("%d",&a[i]); 
            update(i,a[i]); //初始的人数
        }   
        printf("Case %d:\n",count); 
        char oper[11]; 
        while(scanf("%s",oper)==1) 
        { 
            if(strcmp(oper,"End")==0) 
                break; 
            scanf("%d%d",&i,&j); 
            if(strcmp(oper,"Query")==0) 
            { 
                printf("%d\n",Getsum(i,j)); 
            } 
            if(strcmp(oper,"Add")==0) //表示第i个营地增加j个人
            { 
                a[i] += j; 
                update(i,j); 
            } 
            if(strcmp(oper,"Sub")==0) //表示第i个营地减少j个人
            { 
                a[i] -= j; 
                update(i,-j); 
            } 
        } 
    } 
    return 0; 
} 


-------------------------------------------------------------------------------------------------------------------------------
树状数组能快速求任意区间的和:
A[i] + A[i+1] + … + A[j],
设sum(k) = A[1]+A[2]+…+A[k],
则A[i] + A[i+1] + … + A[j] = sum(j)-sum(i-1)。

-------------------------------------------------------
二,每次修改的是一个区间,所求的值是关于某个点的;
-------------------------------------------------------

模板如下:(HDU1556:http://acm.hdu.edu.cn/showproblem.php?pid=1556

其实就是修改了update和sum函数里面的符号。

int Lowbit(int x)  // 2^k
{
	return x&(-x);
}

void update(int i,int x)
{
    while(i>0)
     {
         c[i]+=x;
         i-=Lowbit(i);
     }
}

int sum(int x)
{
    int sum=0;
    while(x<=n)
     {
         sum+=c[x];
         x+=Lowbit(x);
     }
    return sum;
}






  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值