0
点赞
收藏
分享

微信扫一扫

力扣 307. 区域和检索 - 数组可修改

思考的鸿毛 2022-04-04 阅读 54

307. 区域和检索 - 数组可修改

线段数组 

模板(也可根据线段树的图示思考)

class NumArray {
private:
    vector<int> tree;
    vector<int> hj;
    int n;
public:
    //树状数组基本操作 lowbit(x) 是返回 x 的最后一位1及其后面0或空组成的二进制数
    // 9&-9  -> 1001&0111 -> 0001 (二进制) ->1 (十进制)
    int lowbit(int i){
        return i&-i;
    }
    void add(int idx,int v){
        for(int i=idx;i<=n;i+=lowbit(i)) tree[i]+=v;
    }
    int query(int x){
        int ans=0;
        for(int i=x;i>0;i-=lowbit(i)) ans+=tree[i];
        return ans;
    }
    NumArray(vector<int>& nums) {
        hj=nums;
        n=nums.size();
        tree.resize(n+1);
        for(int i=0;i<n;i++){
            add(i+1,nums[i]);
        }
    }
    
    void update(int index, int val) {
        add(index+1,val-hj[index]);
        hj[index]=val;
    }
    
    int sumRange(int left, int right) {
        return query(right+1)-query(left);
    }
};


 

线段树

u<<1与u<<1|1 分别为 tr[u] 的左子节点和右子节点

class Node{
public:
    int l;
    int r;
    int v;
    Node(int _l,int _r){
        l=_l;
        r=_r;
        v=0;
    }
    Node(){}
};

class NumArray {
private:
    vector<Node> tr;
    vector<int> nums;
    //创建 线段树
    void build(int u,int l,int r){
        tr[u]=Node(l,r);
        if(l==r) return;
        int mid=(l+r)>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
    }
    //更新 x 的值 如果要改变某个范围的值传参将x->(l,r)可以 
    void update_2(int u,int x,int v){
        if(tr[u].r==x&&tr[u].l==x) {
            tr[u].v+=v;
            return;
        }
        int mid=(tr[u].l+tr[u].r)>>1;
        if(x<=mid) update_2(u<<1,x,v);
        else update_2(u<<1|1,x,v);
        pubsum(u);
    }
    //求(l,r)范围的值
    int query(int u,int l,int r){
        if(l<=tr[u].l&&tr[u].r<=r) return tr[u].v;
        int mid=(tr[u].l+tr[u].r)>>1;
        int ans=0;
        if(l<=mid) ans+=query(u<<1,l,r);
        if(r>mid) ans+=query(u<<1|1,l,r);
        return ans;
    }
    void pubsum(int u){
        tr[u].v=tr[u<<1].v+tr[u<<1|1].v;
    }
public:
    NumArray(vector<int>& _nums){
        nums=_nums;
        int n=nums.size();
        tr.resize(4*n);
        build(1,1,n);
        for(int i=0;i<n;i++) update_2(1,i+1,nums[i]);
    }
    void update(int index, int val) {
        update_2(1,index+1,val-nums[index]);
        nums[index]=val;
    }
    int sumRange(int left, int right) {
        return query(1,left+1,right+1);
    }
};

举报

相关推荐

0 条评论