题目为力扣307区域和检索 - 数组可修改,模板来自评论区。
class NumArray {
int[] tree, nums;
int n = -1;
public NumArray(int[] nums) {
n = nums.length;
if(n==0) return;
this.nums = nums;
tree = new int[4*n];
build(0, 0, n-1);
}
public void update(int index, int val) {
update(0, 0, n-1, index, val);
}
public int sumRange(int left, int right) {
return query(0, 0, n-1, left, right);
}
// node left right分别为tree的索引 要更新的区间开始索引 要更新的区间结束索引,
// 值分别等于0,0,nums.length-1。
// update()和query()相同
private void build(int node, int left, int right) {
if(left == right) {
tree[node] = nums[left];
return;
}
int mid = left + ((right-left)>>1);
build(node*2+1, left, mid);
build(node*2+2, mid+1, right);
tree[node] = tree[node*2+1] + tree[node*2+2];
}
// idx为要修改的nums数组索引,val为要修改的值
private void update(int node, int left, int right, int idx, int val) {
if(left>right) return;
else if(left == right) {
nums[left] = val;
tree[node] = val;
} else {
int mid = left+((right-left)>>1);
if(idx>=left&&idx<=mid) update(node*2+1, left, mid, idx, val);
else update(node*2+2, mid+1, right, idx, val);
tree[node] = tree[node*2+1] + tree[node*2+2];
}
}
// L为要查询的区间和的区间的起始索引,R为结束索引
private int query(int node, int left, int right, int L, int R) {
if(L > right || R < left) return 0;
else if(left == right) return tree[node];
else if(L <= left && R >= right) return tree[node];
else {
int mid = left + ((right-left)>>1);
return query(node*2+1, left, mid, L, R) + query(node*2+2, mid+1, right, L, R);
}
}
}