Algorithm - 数据结构 - 树状数组(BinaryIndexedTree)

题型: 大量数据, 快速修改某一元素并且能求其中某一段和

原理: 修改某一元素时, 利用快速二分修改与其相关的数据, 也利用二分来进行快速求和

如图, 按照二分来进行求和  C8 = C4 + (C6 + (C7 + C8))

也按照二分来进行修改数据 C1 -> C2 -> C4 -> C8

实现

struct BinaryIndexedTree{
    //数组大小
    int n;    
    //源数组
    int arr[] 
    // 初始化
    void Init(int noa){
        n = noa;
        for(int i = 0; i < n; i ++){
            arr[i] = 0;
        }
    }
    // 快速求下项
    int lowbit(int k){
        return k & -k;
    }
    // 插入
    // index: 位置
    // val: 值
    void insert(int index, int val){
        for(int i = index; i <= n; i += lowbit(index)){
            arr[index] += val;
        }
        /*
        while(index <= n){
            arr[index] += val;
            index = index + lowbit(index);
        }
        */
    }
    // 求和
    // index: 从 0 到 index 区间
    int getSum(int index){
        int sum = 0;
        for(int i = index; i > 0; i -= lowbit(index)){
            sum += arr[index];
        }
        /*
        while(index > 0){
            sum += arr[index];
            index = index - lowbit(index);
        }
        */
        return sum;
    }
}

 

变种题型: 二位树状数组

实现:

struct BinaryIndexedTree{
    //矩阵大小(按照正方形来计算)
    int n;    
    //源矩阵
    int arr[][];
    // 初始化
    void Init(int noa){
        n = noa;
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++_){
                arr[i][j] = 0;
            }
        }
    }
    // 快速求下项
    int lowbit(int k){
        return k & -k;
    }
    // 插入
    // x, y: 坐标位置
    // val: 值
    void insert(int x, int y, int val){
        for(int i = x; i <= n; i += lowbit(i)){
            for(int j = y; j <= n; j += lowbit(j)){
                arr[i][j] += val;
            }
        }
    }
    // 求和
    // x, y: 从 (0, 0) 到 (x, y) 区间
    int getSum(int x, int y){
        int sum = 0;
        for(int i = x; i > 0; i -= lowbit(i)){
            for(int j = y; j > 0; j -= lowbit(j)){
                sum += arr[i][j];
            }
        }
        return sum;
    }
}

 

变种题型: 二位逆置树状数组, 与正常树状数组相反, 改变的是一段区间, 求一个点的值

实现:

struct BinaryIndexedTree{
    //矩阵大小(按照正方形来计算)
    int n;    
    //源矩阵
    int arr[][];
    // 初始化
    void Init(int noa){
        n = noa;
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++_){
                arr[i][j] = 0;
            }
        }
    }
    // 快速求下项
    int lowbit(int k){
        return k & -k;
    }
    // 插入
    // x, y: 坐标位置
    // val: 值
    void insert(int x, int y, int val){
        // 要需要一整片区间的值
        // 从 (x,y) 到 (0,0) 进行迭代
        for(int i = x; i > 0; i -= lowbit(i)){
            for(int j = y; j > 0; j -= lowbit(j)){
                arr[i][j] += val;
            }
        }
    }
    // 求和
    // x, y: 从 (0, 0) 到 (x, y) 区间
    int getSum(int x, int y){
        int sum = 0;
        // 要求一点的和
        // 从 (x, y) 到 (n, n) 进行迭代
        for(int i = x; i <= n; i += lowbit(i)){
            for(int j = y; j <= n; j += lowbit(j)){
                sum += arr[i][j];
            }
        }
        return sum;
    }
}

 

posted @ 2016-12-27 10:03  `Laimic  阅读(147)  评论(0)    收藏  举报