樹狀陣列求序列的區間和
阿新 • • 發佈:2019-02-15
給你一個序列,求任意區間的和。
樹狀陣列的思路:
這樣的結構關鍵是為了,對一個數組內部動態的刪除,增加,來高效的求某個點或者某個區間的值;
比如說對陣列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)); } }