2022/04/04 leetcode 每日一题 307. 区域和检索 - 数组可修改(线段树)

1.题目

2022/04/04 leetcode 每日一题 307. 区域和检索 - 数组可修改(线段树)_第1张图片

2.求解

这道题看通过率,一半,也说明了应该也是道简单题,很简单的线段树,甚至感觉用线段树都有些奢侈,因为这道题没有用到区域修改(个人认为这才是线段树的精髓)。除此之外区域求和也是线段树的一个特点,因此也是很容易想到要用线段树求解。(我虽然想到了 但是太久没做线段树的题目了导致我忘了流程是啥样的)

那么说啥都没有直接上代码来的直接,冲冲冲!

3.代码

class NumArray {
public:
    
    int Sum[30005 << 2];
    int len ;
    void PushUp(int rt){
        Sum[rt] = Sum[rt<<1] + Sum[rt<<1|1];
    }
    void Build(int l, int r, int rt, vector& nums){
        if(l == r){
            Sum[rt] = nums[l];
            return ;
        }
        int m=(l+r)>>1;
        Build(l,m,rt<<1, nums);
        Build(m+1,r,rt<<1|1, nums);
        PushUp(rt);
    }
    //建树一定要注意虽然给的vector下标从0 - len-1但是创建的线段树一定要从1开始
    //因为用到了位运算向左推一位的时候如果为0的情况推完还是0会覆盖之前的数据 千万注意!!!
    void Update(int index, int val, int l, int r, int rt){
        if(l == r){
            Sum[rt] = val;
            return ;
        }
        int m = (l + r) >> 1;
        if(index <= m) Update(index, val, l, m, rt << 1); 
        if(index > m) Update(index, val, m + 1, r, rt << 1|1);
        PushUp(rt);

    }

    int Query(int L, int R, int l, int r, int rt){
        if(L <= l && r <= R) return Sum[rt];
        int m = (l + r) >> 1;
        // PushDown(rt, m - l + 1, r - m);

        int ans = 0;
        if(L <= m) ans += Query(L, R, l, m, rt << 1);
        if(R > m) ans += Query(L, R, m+1, r, rt<<1|1);
        return ans;
    }
    NumArray(vector& nums) {
        len = nums.size();
        Build(0, nums.size() - 1, 1, nums);

        PushUp(0);
    }
    
    void update(int index, int val) {
         Update(index, val, 0, len - 1, 1);
    }
    
    int sumRange(int left, int right) {
        return Query(left, right, 0, len - 1, 1);
    }
};

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray* obj = new NumArray(nums);
 * obj->update(index,val);
 * int param_2 = obj->sumRange(left,right);
 */

我的代码部分可能有些复杂,因为太久没写了大家酌情看 别骂我菜:)

你可能感兴趣的:(Leetcode刷题,leetcode,算法)