1. 程式人生 > >樹狀陣列(模板)

樹狀陣列(模板)

題目分析

將一組陣列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)。

-------------------------------------------------------
二,每次修改的是一個區間,所求的值是關於某個點的;
-------------------------------------------------------

其實就是修改了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;
}