数据结构——树状数组

树状数组(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了;
像离散化处理,二维树状数组。。。

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