/**
 * 线段树类
 * @param {number[]} nums
 */
var SeqTree = function (nums) {
  this.nums = nums;
  this.tree = new Array(4 * nums.length).fill(0);
  this.build(0, 0, nums.length - 1);
};

/**
 * 建树方法
 * @param {*} node 当前树节点
 * @param {*} start 当前树节点涵盖范围的起点
 * @param {*} end 当前树节点涵盖范围的终点
 * @return {void}
 */
SeqTree.prototype.build = function (node, start, end) {
  if (start === end) {
    this.tree[node] = this.nums[start];
    return;
  }
  const mid = start + Math.floor((end - start) / 2);
  const leftNode = 2 * node + 1;
  const rightNode = 2 * node + 2;
  this.build(leftNode, start, mid);
  this.build(rightNode, mid + 1, end);
  this.tree[node] = this.tree[leftNode] + this.tree[rightNode];
};

/**
 * 对外使用的更新方法
 * @param {number} index 需要修改的节点下标
 * @param {number} val 需要修改的数值
 * @return {void}
 */
SeqTree.prototype.update = function (index, val) {
  this.change(0, 0, this.nums.length - 1, index, val);
};

/**
 * 更新树节点
 * @param {*} node 当前树节点
 * @param {*} start 涵盖范围的起点
 * @param {*} end 涵盖范围的终点
 * @param {*} idx 需要修改的节点下标
 * @param {*} val 需要修改的数值
 * @return {void}
 */
SeqTree.prototype.change = function (node, start, end, idx, val) {
  if (start === end) {
    this.tree[node] = val;
  } else if (idx < start || end < idx) {
    return;
  } else {
    const mid = start + Math.floor((end - start) / 2);
    const leftNode = 2 * node + 1;
    const rightNode = 2 * node + 2;
    if (start <= idx && idx <= mid) {
      this.change(leftNode, start, mid, idx, val);
    } else {
      this.change(rightNode, mid + 1, end, idx, val);
    }
    this.tree[node] = this.tree[leftNode] + this.tree[rightNode];
  }
};

/**
 * 对外使用的区间求和方法
 * @param {number} left 查询区间的左节点
 * @param {number} right 查询区间的右节点
 * @return {number} 返回区间和
 */
SeqTree.prototype.sumRange = function (left, right) {
  return this.query(0, 0, this.nums.length - 1, left, right);
};

/**
 * 查询范围的和
 * @param {*} node 当前树节点
 * @param {*} start 涵盖范围的起点
 * @param {*} end 涵盖范围的终点
 * @param {*} l 查询区间的左节点
 * @param {*} r 查询区间的右节点
 * @return {number} 返回区间和
 */
SeqTree.prototype.query = function (node, start, end, l, r) {
  if (r < start || end < l) {
    return 0;
  } else if (l <= start && end <= r) {
    return this.tree[node];
  } else {
    const mid = start + Math.floor((end - start) / 2);
    const leftNode = 2 * node + 1;
    const rightNode = 2 * node + 2;
    const leftSum = this.query(leftNode, start, mid, l, r);
    const rightSum = this.query(rightNode, mid + 1, end, l, r);
    return leftSum + rightSum;
  }
};

Q.E.D.


我还有很多想要完成的梦想。