решение дерева:
создайте полное дерево, листья которого являются вашими входами: 1,2, ..., n
node.value = inserted value [if node is a leaf]
node.value = node.left.value + node.right.value [if node is not a leaf]
так, на самом деле - для каждого поддерева значение его корня является суммой значений всех его узлов.
обновление записи - это O (logn), так как вам нужно обновлять суммы вплоть до корня.
для суммы (i, j) мы найдем сумму всех элементов слева от i и всех элементов справа от j и вычтем ее из root.value, и мы получим то, что нам нужно.так:
sum(root,i,j) = root.value - sumLeft(i,root) - sumRight(j,root)
расчет sumLeft()
и sumRight()
прост, [для sumLeft:] просто начните с корня вниз до нижней границы, и каждый раз, когда вы идете влево, вычитайте правуюТаким образом, вы вырезаете из суммы не нужные узлы.[убедите себя, почему это так].в конце сумма имеет только релевантные узлы.тот же принцип для sumRight, но вместо этого мы вычитаем левых сыновей.
псевдокод:
sumLeft(x,root):
curr <- root
sum <- root.value
while (curr is not a leaf):
if (x is in curr.right):
curr <- curr.right
else:
sum <- sum - curr.right.value
curr <- curr.left
return sum
sumRight(x,root):
curr <- root
sum <- root.value
while (curr is not a leaf):
if (x is in curr.left):
curr <- curr.left
else:
sum <- sum - curr.left.value
curr <- curr.right
return sum
Итак, sum (root, i, j) требует от вас дважды спуститься по дереву, которое по-прежнему равно O (logn).
РЕДАКТИРОВАТЬ1:
это то, как вы добавляете x к элементу i на корне: [вопрос указывает на то, что опора добавляет элемент, а не заменяет его, так что эторешение предполагает.его также можно легко модифицировать для вставки].
add(root,i,x):
root.value <- root.value + x
if root is leaf:
return
else if i is in root.left:
add(root.left,i,x)
else:
add(root.right,i,x)
обратите внимание, что вы можете точно знать, какому поддереву (левому или правому) корня принадлежит запись, которой принадлежит [если i < n/2
слеваостальное справа.объясните себе, как это делается для любого поддерева, а не только для корня.
РЕДАКТИРОВАТЬ 2:
пример для дерева с 8 элементами:
21
10 11
4 6 7 4
1 3 2 4 6 1 2 2
обобщить пример:
сумма (4,6) должна предоставить 4 + 6 + 1 = 11
.
sumLeft (4) должен предоставить 1 + 3 + 2 = 6
, и он обеспечивает: sumLeft(4) = 21 - 11 - 4 = 6
, как и ожидалось.
sumRight (6) должен предоставить 2 + 2 = 4
, а он обеспечивает sumLeft(6) = 21 - 11 - 7 =4
.[как ожидается]
так, в целом: sum(4,6) = 21 - 6 - 4 = 11
, как и ожидалось.
добавить пример:
добавить (2,4) [добавление 4 ко 2-му элементу]приведет к изменению дерева на:
25
14 11
8 6 7 4
1 7 2 4 6 1 2 2