Here is a method to find the depth of every node in
Unable to parse markup [type=CF_MATHJAX]
$ operations.
Root the tree at
Unable to parse markup [type=CF_MATHJAX]
$, and let
Unable to parse markup [type=CF_MATHJAX]
$.
Take a power of two
Unable to parse markup [type=CF_MATHJAX]
$ such that
Unable to parse markup [type=CF_MATHJAX]
$. Since the depth of any node in the tree is less than
Unable to parse markup [type=CF_MATHJAX]
$, initially we can assume that the depth of every non-root node lies in
Unable to parse markup [type=CF_MATHJAX]
$.
Then we keep binary-splitting this interval.
Suppose that currently every node belongs to a depth segment of length
Unable to parse markup [type=CF_MATHJAX]
$. For a node
Unable to parse markup [type=CF_MATHJAX]
$, let
Unable to parse markup [type=CF_MATHJAX]
$ be the index of the segment it currently belongs to, that is:
Unable to parse markup [type=CF_MATHJAX]
$
In each binary-splitting round, we want to determine whether each node is in the left half or the right half of its current segment.
Consider processing all segments in parallel by grouping their indices modulo
Unable to parse markup [type=CF_MATHJAX]
$.
For
Unable to parse markup [type=CF_MATHJAX]
$, we make one query:
- if
Unable to parse markup [type=CF_MATHJAX]
$, set
Unable to parse markup [type=CF_MATHJAX]
$; - otherwise, set
Unable to parse markup [type=CF_MATHJAX]
$.
This query can split all nodes satisfying
Unable to parse markup [type=CF_MATHJAX]
$.
Consider a node
Unable to parse markup [type=CF_MATHJAX]
$ whose side we want to determine, and suppose the index of its segment is
Unable to parse markup [type=CF_MATHJAX]
$. The only nodes that can actually affect it are those in the previous segment
Unable to parse markup [type=CF_MATHJAX]
$.
All other selected segments are at least two full depth segments away from the segment of
Unable to parse markup [type=CF_MATHJAX]
$, so their distance to
Unable to parse markup [type=CF_MATHJAX]
$ must be greater than
Unable to parse markup [type=CF_MATHJAX]
$, and they will not light up
Unable to parse markup [type=CF_MATHJAX]
$.
Therefore:
- if
Unable to parse markup [type=CF_MATHJAX]
$ is in the left half of its current segment, then after moving
Unable to parse markup [type=CF_MATHJAX]
$ steps towards the root, it reaches the previous segment, so it will be lit up; - if
Unable to parse markup [type=CF_MATHJAX]
$ is in the right half of its current segment, then its distance to every node in the previous segment is greater than
Unable to parse markup [type=CF_MATHJAX]
$, so it will not be lit up.
Thus, from the query result, we can directly determine which half
Unable to parse markup [type=CF_MATHJAX]
$ should enter.
There is also the case
Unable to parse markup [type=CF_MATHJAX]
$: the first segment has no previous segment, so we additionally need to set
Unable to parse markup [type=CF_MATHJAX]
$ for the root.
Each round only needs
Unable to parse markup [type=CF_MATHJAX]
$ queries, and there are
Unable to parse markup [type=CF_MATHJAX]
$ rounds. Therefore, the number of queries needed to find all depths is at most:
Unable to parse markup [type=CF_MATHJAX]
$.
In fact, with some small optimizations, the number of queries can be reduced by a few more. Also, this method is more consistent with the official editorial's method for finding the parent of each node.
Translated with the assistance of ChatGPT.



