
So far, we have constructed a tree that represents the information of the end-points of the segments plus
the dummy nodes ∞ and −∞. Obviously, this is not sufficient for answering a stabbing query.
Additionally, we have to incorporate the information of the segments into the tree. Therefore, let us
consider a single segment s represented by the x-coordinates (e
j
, e
k
) of its endpoints. The segment s can
be represented by a consecutive set of elementary intervals. We choose a minimal set of elementary
intervals (or the corresponding nodes) in the one-dimensional search tree so that s is fully covered. Due
to Algorithm 2.3, every node represents an elementary interval v.I and, if necessary, its data points.
Minimal means that the nodes are chosen as close as possible to the root of the tree; see Figure 2.2. We
store s in each of the associated nodes. More precisely, let v .pred be the predecessor of v in the interval
tree. A segment s = (e
j
, e
k
) represented by the x-coordinates of the endpoints is stored in a list v. L at v iff
v.I ⊆ [e
j
, e
k
] and (v.pred). I [e
j
, e
k
]. Thus, each node represents an elementary interval v.I and a list of
segments v.L; for an example, see Figure 2.3.
Figure 2.3: The query procedure for a segment tree and a query line l. The shaded intervals indicate the
query path from the root to the leaf. All segments stored at the corresponding nodes are reported.
The one-dimensional search tree with intervals v.I is built up in O(n log n) time, as was shown previously.
However, we need to show how the segment partitions are inserted into the tree. This is done by the
following recursive insert procedure, which has to run for every segment s = (e
j
, e
k
).
The following is the sketch of the segment insertion in the one-dimensional search tree:
Input: given a line segment s = (e
j
, e
k
) and the root v of the segment tree;
If the interval v.I is already a subset of the interval [e
j
, e
k
], then insert s into the segment set v.L and
stop;
Otherwise, let v. LeftChild and v. RightChild be the children of v. This means that the interval v.I
equals (v.LeftChild).I ∪ (v. RightChild).I;
o If the interval [e
j
, e
k
] and the set (v. LeftChild).I overlap, then run the insert procedure
recursively with s and the segment tree v. LeftChild;
o If the interval [e
j
, e
k
] and the set (v. RightChild).I overlap, then run the insert procedure
recursively with s and the segment tree v. RightChild.
By inserting every segment into the one-dimensional search tree of the line segment‘s endpoints, we will
finally obtain the segment tree. Altogether, Algorithm 2.4 constructs the segment tree by using Algorithm
2.5 as a subroutine. Note that S
x
. Extend extends S
x
by the dummy elements ∞ and −∞.
Lemma 2.4. The segment tree for n segments can be built in O(n log n) and uses O(n log n) space.
Proof: The binary tree has depth O(logn) and O(n) nodes. At each level of the segment tree T, a segment
s = (e
j
, e
k
) is stored at most twice. To prove this fact, let us assume that three nodes u
l
, u
m
, and u
r
of the
same level in T contain the segment s. The intervals of their parents do not overlap. This is because they
can overlap only if a pair of u
l
, u
m
, and u
r
has a common predecessor. In this case, the segment has to be
inserted for the predecessor. If the intervals of the parents of u
l
, u
m
, and u
r
do not overlap, the
intermediate node of u
l
, u
m
, and u
r
must have a parent whose interval fully contains [e
j
, e
k
]; therefore, s is