樹狀陣列(模板)
阿新 • • 發佈:2019-02-03
題目分析
將一組陣列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; }