3

I am struggling with exercise from the old algorithmic exam:
$d$ is const for the whole structure. Propose a structure for which you can do:

  • Init(S) //called only 1 time
  • Insert(x, S):: $ S := S \cup \{x\}$ in O(log(|S|)
  • Delete(x, S):: $ S := S \setminus \{x\}$ in O(log(|S|)
  • Get(S) = $| \{ a,b \} \subset S : a+b \le d|$ in O(1)

I am trying to that with AVL Tree with additional members like number of nodes such that $v.value+u.value \le d$.
Could somebody give me some hint?

greybeard
  • 1,172
  • 2
  • 9
  • 24
TurboGuma
  • 207
  • 1
  • 5

1 Answers1

2

It is on the right direction to try some kind of tree augmented with a global counter that stores the number of all unordered pairs of nodes $\{u,v\}$ such that $v.value+u.value \le d$.

The kind of tree you are looking for is a balanced (binary) search tree. Being balanced such as an AVL tree, it supports insertion, deletion and lookup of a number with $O(\log|S|)$ time. Being sorted as well, it can also update that global counter in $O(\log|S|)$ time if we can maintain some extra information on each node of the tree.

What should be those extra information? One approach is that each node $v$ will have a member $lcount$ that stores the number of nodes in its left subtree as well as a member $rcount$ that stores the number of nodes in its right subtree.

To simplify the explanation, let us use AVL tree. We will assume all values are distinct; otherwise, we can add a duplicity counter to each node.

Each insertion or deletion involves at most two tree rotations. Each rotation changes the edges between at most several nodes. So we can update all $lcount$ and $rcount$ in $O(\log|S|)$ time.

Before the insertion of node $n$, we should compute the number of nodes whose values are not greater than $d - n.value$, which is one plus the number of nodes to the left of the node $m$, whose value is the greatest but no greater than $d-n.value$. With the insertion of $n$, we will keep the global_counter intact if there is no such node $m$. Otherwise, letting $ancestor$ be $m$, we will do the following.

while ancestor is not null:
  if anc.value < m.value:
    global_counter := global_counter + ancestor.lcount + 1
  ancestor := ancestor.parent

The case of deletion is similar to the case of insertion.

Further explanation will be omitted.


Thanks to OP, who contributed to this answer.

John L.
  • 39,205
  • 4
  • 34
  • 93