- Advantage: Easy to implement and understand
- Disadvantage: Requires more memory
- Root Node:
1 - We store
2^{k+1}elements data[2^k..2^{k+1})represent the range[0, ..., 2^k).- The 2 power number of bits in
2^{k+1} / (idx + 1)gives us the length of the range represented by the node.
- Formula to find exact range covered by the node
idx. - For every range, find the 2 nodes and the corresponding lca.
- Consider the range
[left, right). - There's an lca with range, say
[lca_left, lca_right). - There are nodes with range
[left, left_node_right)and[right_node_left, right). left_node_leftandright_node_rightjust correspond toleftandrightrespectively.- For simiplicity, let's call them
left_idx,right_idxandlca_idx.
-
Consume: Operation to determine how the updates behave with the nodes.
consume(update, (mutable) data, size) -
Propagate: Here, we are just adding some update to the already existing tag in our node.
Note: Propagate is only defined for non-leaf nodes.
The pseudocode for
propagate(idx, update_val):- If the children are leaves, just let them
consume(.., &.., 1)the update. - if
update_leftis the update at left node, set it toupdate_left + update_val - if
update_rightis the update at right node, set it toupdate_right + update_val
- If the children are leaves, just let them
-
Push node: Here, we are consuming any range update to the node and propagating it to its children.
The pseudocode for
push(idx):- If
idxis a leaf node, return. - Store the update at the node
idxin a variable, sayexisting_update - Consume the update at
idx - Propagate
propagate(idx_child, existing_update)to it's children.
- If
-
Push node with update: Here, we have another update to push to the children.
The pseudocode for
push_with_update(idx, update_val):- If
idxis a leaf node, return. - Store the update at the node
idxin a variable, sayexisting_update - Consume the update at
idx - Propagate the update
existing_updateto it's children. - Propagate the update
update_valto it's children.
- If
-
Push nodes: Here, we are pushing the node along some path.
The pseudocode for
push_nodes(idx_from, idx_to):push(idx_from)- if
idx_fromisidx_to, return. - We want to determine if
idx_tobelongs to the left_subtree or the right. - if
idx_tolies in the left child ofidx_from,push_nodes(idx_from * 2) - if
idx_tolies in the right child ofidx_from,push_nodes(idx_from * 2 + 1)
-
Push nodes with update: Here, we are pushing the node along some path with an update.
The pseudocode for
push_nodes_with_update(idx_from, idx_to, update_val):push_with_update(idx_from, update_val)- if
idx_fromisidx_to, return. - We want to determine if
idx_tobelongs to the left_subtree or the right. - if
idx_tolies in the left child ofidx_from,push_with_update(idx_from * 2, update_val) - if
idx_tolies in the right child ofidx_from,push_with_update(idx_from * 2 + 1, update_val)
-
Pull node: Here, we want to make sure the data in the children is up-to-date.
The pseudocode for
pull(idx)(Make sure the node is pushed)- If it's a leaf node, ignore.
- Otherwise,
push(idx_child)the children. - Recompute data at this node.
-
Pull nodes: Here, we want to make sure the data in the children is up-to-date.
The pseudocode for
pull_nodes(idx_from, idx_to): (We assume the nodes have been pushed)pull(idx_from)(if not done already)- start a while loop here with
idx = idx_from push(idx ^ 1)(the sibling ofidx)- Recompute data at this node
- if
idx_fromisidx_to, break. - Set
idx = idx / 2and continue
-
Query: Query the range
[left, right).The pseudocode for
query(left, right):- Find the
idx_left,idx_right,idx_lca. push_nodes(idx_root, idx_lca)push_nodes(idx_lca, idx_left)push_nodes(idx_lca, idx_right)pull_nodes(idx_left, idx_lca)pull_nodes(idx_right, idx_lca)pull_nodes(idx_lca, idx_root)
- Find the
-
Update: Update the range
[left, right).The pseudocode for
update(left, right, update)- Find the
idx_left,idx_right,idx_lca. push_nodes_with_update(idx_root, idx_lca, update)push_nodes_with_update(idx_lca, idx_left, update)push_nodes_with_update(idx_lca, idx_right, update)pull_nodes_update(idx_lca, idx_left, update)pull_nodes_update(idx_lca, idx_right, update)pull_nodes_update(idx_lca, idx_root, update)
- Find the