數據結構——樹狀數組

樹狀數組(Beautiful數據結構)

樹狀數組,又名前綴樹,是很實用的工具,顧名思義樹狀數組(樹型結構的數組,一種存儲方式)
!!!!!由子樹構成的大樹,大數;
在這裏插入圖片描述
上圖就是其形象的結構圖樣。A[1]->C[1] ; C[2]->A[1]+A[2] ; C[3]->A[3] ; C[4]->C[2]+C[3]->A[1]+A[2]+A[3]+A[4] ; C[5]->A[5] ; C[6]->A[5]+A[6] ; C[7]->A[7] ; C[8]->A[1]+…+A[8]
注意節點區間和變成了1,2,4,8,16…
此時找一下規律
以5 爲例子二進制表示0101,若減去0001—>變成0100,4節點。若加上0001---->變成0110再加上0010---->變成1000,8節點。發現要是提取了一個數的最後一位,加上它或者減去它,正好就是二進制中的1,2,4,8,16…
這只是數字遊戲罷了,只要找到末尾的1,就能依次到1,10,100,100000000000,因爲這是我們要建立的樹而已。由子樹到參天大樹。
現在就來就找數字的最後一位1,

   #define lowbit(x) x&(-x)    //每一次將其寫在代碼前面方便使用;

就拉一道模版題出來吧:
題意很簡單,就是有N個數,兩種操作1.查詢任意區間和。2.在任意位置加或減去一個數。
代碼給詳解:

相對於線段樹,樹狀數組真的是性價比超高了呢《----》

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#define lowbit(x) x&(-x)    //超方便的取位方法,0不能用啊,不然就死循環了。
using namespace std;
const int N=1e5+55;
int tree[N];             //數組tree,樹狀的結構,不開long long 見祖宗。。。。。
void add(int x, int val)   //前綴和;
{
    if(!x) return ;
    while(x<=N){
        tree[x]+=val;
        x+=lowbit(x);    // x本身也加上了哦 //將數據依次向上推入,加加加加,是向上的;
    }
}
int search_tree(int x)
{
    int ans=0;           //將所有子樹都加到位好吧;
    while(x>0){
        ans+=tree[x];
        x-=lowbit(x);  //需要注意x位置的值也算入了 //向下取和,建議手動模擬一遍印象更深刻德瑪;
    }
    return ans;
}
int main()
{
    int n,m,i,x,y,val,k,sum1,sum2;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++){
        scanf("%d",&val);
        add(i,val);             //加加加入;
    }
    for(i=0;i<m;i++){
        scanf("%d",&k);
        if(k==1){
            scanf("%d%d",&x,&y);
            sum1=search_tree(x-1);    //x本身也加上了故爲(x-1);
            sum2=search_tree(y);
            printf("%d\n",sum2-sum1);
        }
        else{
            scanf("%d%d",&x,&val);
            add(x,val);
        }
    }
    return 0;
}

若是實際應用還牽扯到其他知識點,多做些題就OK了;
像離散化處理,二維樹狀數組。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章