1. 程式人生 > >樹狀陣列求序列的區間和

樹狀陣列求序列的區間和

給你一個序列,求任意區間的和。

樹狀陣列的思路:


這樣的結構關鍵是為了,對一個數組內部動態的刪除,增加,來高效的求某個點或者某個區間的值;

比如說對陣列a,改變某一位的值需O(1),求某個k區間值O(k);

這樣的m次操作是用O(m*k);

顯然資料很大時,效率要差很多;

而樹狀陣列,它改變某一位,或者求某個區間的和,都是O(logN);效率大為改善;

對於上圖怎麼計算區間的和;關鍵是需要幾個函式;

先說樹狀陣列最簡單的用法,修改上面圖中的某個點,並求某段區間的和

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
   int n;
   int a[100];
   int c[100];
int lowbit(int x){//可以打出來看一下,返回x與2^64的最大公約數,即x最多能被n個2整除就返回2^n;如果x是奇數返回1
return x&(-x); } void build(int p,int num){也可以作為修改用,p位置加上sum(也可以用減) while(p<=n){ c[p]+=num; p+=lowbit(p); } } int sum(int x){//求和,求前x個數的和 int ans=0; while(x>0){ ans+=c[x]; x-=lowbit(x); } return ans; } int main(){ int i,l,r; while(scanf("%d",&n)!=EOF){ memset(c,0,sizeof(c)); for(i=1;i<=n;i++){ scanf("%d",&a[i]); build(i,a[i]);//建數 } for(i=1;i<=n;i++){ printf("sum[i]=%d c[i]=%d\n",sum(i),c[i]);//c陣列就是圖中建的樹狀陣列 } scanf("%d%d",&l,&r);//查詢區間l~r的和 printf("%d\n",sum(r)-sum(l-1)); } }