树状数组(模板)

转载请注明出处: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   
#include   
#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;
}






你可能感兴趣的:(模板篇,树状数组,树状数组)