Leetcode 307
这是今天做的一个题 307. 区域和检索 - 数组可修改
和 303. 区域和检索 - 数组不可变 不同的是 数组可修改
上一个dalao的分析 , 放弃996了
/**
 * 数组不变,求区间和:「前缀和」、「树状数组」、「线段树」
 *
 * 多次修改某个数,求区间和:「树状数组」、「线段树」
 *
 * 多次整体修改某个区间,求区间和:「线段树」、「树状数组」(看修改区间的数据范围)
 *
 * 多次将某个区间变成同一个数,求区间和:「线段树」、「树状数组」(看修改区间的数据范围)
 *
 */
学了个树状数组方法。
class NumArray {
    int[] tree;
    int lowBits(int x){
        return x & -x;//保留二进制下最后出现的1的位置,其余位置置0
    }
    //当一个偶数与它的负值向与时,结果是能被这个偶数整除的最大的2的n次幂 , 比如10返回2
    //当一个奇数与它的负值向与时结果一定是1
    // 查询前缀和的方法
    int query(int x){
        int ans = 0;
        for (int i = x; i > 0 ; i -= lowBits(i)) {
            ans += tree[i];
        }
        return ans;
    }
    // 在树状数组 x 位置中增加值 u
    void add(int x ,int u){
        for (int i = x; i <= n ; i += lowBits(i)) {
            tree[i] += u;
        }
    }
    int[] nums;
    int n;
    // 初始化「树状数组」
    public NumArray(int[] nums) {
        this.nums = nums;
        n = nums.length;
        tree = new int[n + 1];
        for (int i = 0; i < n; i++) {
            add(i + 1, nums[i]);
        }
    }
    // 原有的值是 nums[i],要使得修改为 val,需要增加 val - nums[i]
    public void update(int index, int val) {
        add(index + 1 , val - nums[index]);
        nums[index] = val;
    }
    public int sumRange(int left, int right) {
        return query(right + 1) - query(left);
    }
}