如果你想实际修改数组,你不能比简单的线性算法做得更好:你必须迭代整个范围并相应地修改每个索引。
如果你的意思是,你有像你描述的更新操作和查询操作find the sum in the range from x to y,那么段树可以帮助这样。
对于每个更新操作left, right, value,对于每个具有包含在[left, right] 中的关联范围的节点,其总和将乘以value,因此相应地更新它并停止进行递归。这也适用于您不会递归的间隔,因此不是实际更新总和,而是在每个节点中存储其关联间隔乘以多少。
当从递归返回时,您可以根据此信息重新计算实际总和。
伪代码:
Update(node, left, right, value):
if [left, right] does not intersect node.associated_range:
return
if [left, right] included in node.associated_range:
node.multiplications *= value # 1 initially
return
Update(node.left, left, right, value)
Update(node.right, left, right, value)
node.sum = node.left.sum * node.left.multiplications +
node.right.sum * node.right.multiplications
基本上,每个节点将通过仅考虑子段中的乘法来存储其总和。它的真实总和将在查询期间通过使用有关影响该间隔的乘法的信息来延迟计算。
然后执行求和查询几乎就像对段树的常规查询一样:只需确保将总和乘以它们或父区间乘以的数量。
伪代码:
Query(node, multiplications = 1, left, right):
if [left, right] does not intersect node.associated_range:
return 0
if [left, right] included in node.associated_range:
return node.sum * multiplications
return Query(node.left, multiplications * node.multiplications, left, right) +
Query(node.right, multiplications * node.multiplications, left, right)
最初构建树的函数留作练习(您可以做得比调用 update n 次更好)。