Algorithm Search⌘K

Proofs: Sweep status structure

These are the human proofs of Sweep status structure, at full length.

The sweep status keeps the active segments in their order along the sweep line full

This proof shows: correctness.

We use the pseudocode of the page. SS is a finite set of segments, none vertical, no two overlapping (two distinct segments share at most one point). A segment ss has endpoints (x1(s),y1(s))(x_1(s), y_1(s)) and (x2(s),y2(s))(x_2(s), y_2(s)) with x1(s)<x2(s)x_1(s) < x_2(s), slope msm_s, and ys(x)y_s(x) for x∈[x1(s),x2(s)]x \in [x_1(s), x_2(s)] as on the page. For a position xx, the active set is A(x)={s∈S:x1(s)≤x<x2(s)}A(x) = \{ s \in S : x_1(s) \le x < x_2(s) \}, and the key at xx is κx(s)=(ys(x),ms)\kappa_x(s) = (y_s(x), m_s), compared lexicographically.

Lemma 1 (keys are distinct). If s≠ts \ne t are both in A(x)A(x), then κx(s)≠κx(t)\kappa_x(s) \ne \kappa_x(t).

Proof. If ys(x)=yt(x)y_s(x) = y_t(x) and ms=mtm_s = m_t, both segments lie on the same line through (x,ys(x))(x, y_s(x)), and both contain the points of that line with abscissa in [x,min⁡(x2(s),x2(t))][x, \min(x_2(s), x_2(t))], an interval of positive length since x<x2(s)x < x_2(s) and x<x2(t)x < x_2(t). So they share infinitely many points and overlap, a contradiction. □\square

Lemma 2 (the key order is the order just to the right). Let s,t∈A(x)s, t \in A(x) with s≠ts \ne t. There is an ε>0\varepsilon > 0 such that κx(s)<κx(t)\kappa_x(s) < \kappa_x(t) if and only if ys(x′)<yt(x′)y_s(x') < y_t(x') for each x′∈(x,x+ε)x' \in (x, x + \varepsilon).

Proof. For x′x' in both domains, f(x′)=ys(x′)−yt(x′)=(ys(x)−yt(x))+(ms−mt)(x′−x)f(x') = y_s(x') - y_t(x') = (y_s(x) - y_t(x)) + (m_s - m_t)(x' - x). If ys(x)≠yt(x)y_s(x) \ne y_t(x), then by continuity ff has the sign of ys(x)−yt(x)y_s(x) - y_t(x) on some interval (x,x+ε)(x, x + \varepsilon), and that sign decides κ\kappa. If ys(x)=yt(x)y_s(x) = y_t(x), then ms≠mtm_s \ne m_t by Lemma 1, and f(x′)=(ms−mt)(x′−x)f(x') = (m_s - m_t)(x' - x) has the sign of ms−mtm_s - m_t for each x′>xx' > x, which again decides κ\kappa. □\square

Lemma 3 (no crossing, no change of order). Let s,ts, t be two segments that both span the closed interval [u,v][u, v] with u<vu < v, and that have no common point with abscissa in the open interval (u,v)(u, v). Then the sign of ys(x′)−yt(x′)y_s(x') - y_t(x') is the same nonzero value for each x′∈(u,v)x' \in (u, v), and the same sign, or zero, at uu and at vv.

Proof. The function f(x′)=ys(x′)−yt(x′)f(x') = y_s(x') - y_t(x') is affine on [u,v][u, v]. It has no zero in (u,v)(u, v), since a zero is a common point. An affine function with a sign change on an interval has a zero inside it (it is continuous), so ff has one sign on (u,v)(u, v). By continuity, f(u)f(u) and f(v)f(v) have this sign or are 00. □\square

The sweep. The event positions are x(1)<x(2)<⋯<x(r)x^{(1)} < x^{(2)} < \cdots < x^{(r)}: the abscissas of all endpoints and of all points that two segments of SS share. At each event position xx, the sweep does, in this order:

  1. SET-X(T,x)(T, x);
  2. DELETE(T,s)(T, s) for each stored ss with x2(s)=xx_2(s) = x;
  3. for each point pp with abscissa xx through which two or more stored segments pass, reverse the contiguous block of these segments (SWAP when there are two);
  4. INSERT(T,s)(T, s) for each ss with x1(s)=xx_1(s) = x.

Claim. After step 4 at the event position xx, the list TT holds exactly A(x)A(x), sorted by κx\kappa_x in increasing order. Each ABOVE, BELOW and NEIGHBORS-OF-POINT made at this moment returns the neighbors in the order of A(x)A(x) just to the right of xx.

Proof. By induction on the events. Before the first event TT is empty, and the steps at x(1)x^{(1)} are the step below with an empty list.

Step. Assume the claim after the event u=x(j)u = x^{(j)}, and let v=x(j+1)v = x^{(j+1)}. Between them no segment starts or ends and no two segments meet (each meeting point is an event), so each s∈A(u)s \in A(u) spans [u,v][u, v], by u<x2(s)u < x_2(s) and the fact that x2(s)x_2(s) is an event position, so x2(s)≥vx_2(s) \ge v.

SET-X. Let s,ts, t be two consecutive entries of TT, ss first. By the hypothesis κu(s)<κu(t)\kappa_u(s) < \kappa_u(t), so by Lemma 2 ys<yty_s < y_t at some points of (u,v)(u, v). By Lemma 3, ys<yty_s < y_t on all of (u,v)(u, v) and ys(v)≤yt(v)y_s(v) \le y_t(v). So after line L1 the values ys(v)y_s(v) do not decrease along TT (the y-order), and the entries that tie at vv are consecutive. Two entries that tie at vv share the point (v,y)(v, y).

LOCATE under the y-order. Line L4 is a binary search for the first position whose value is at least ys(v)y_s(v); it is correct because the values do not decrease. All entries with the value ys(v)y_s(v) follow it contiguously, and ss is one of them, so the loop of lines L5 to L8 reaches ss and returns its position. It stops after at most bb iterations, where bb is the size of the block, because ii grows by 1 each time and the block ends.

Step 2. DELETE removes one entry; a sublist of a list with the y-order has the y-order. After step 2, TT holds the s∈A(u)s \in A(u) with x2(s)>vx_2(s) > v.

Step 3. Let p=(v,y)p = (v, y) and BB the block of stored segments through pp, ∣B∣≥2|B| \ge 2. Each of them has x2>vx_2 > v and x1≤u<vx_1 \le u < v, so pp is interior to each. By the SET-X paragraph, the block is in increasing order of yy on (u,v)(u, v), so just to the left of vv. For x′<vx' < v close to vv, ys(x′)=y−ms(v−x′)y_s(x') = y - m_s (v - x'), so increasing order of yy just left of vv is decreasing order of slope. Reversing the block gives increasing order of slope, which is κv\kappa_v order inside the block, since all have the same yy. For two segments the reversal is line L14, and the precondition of SWAP holds: tt is directly above ss and they meet at pp. Reversal moves entries only inside a block of equal values, so the y-order holds. After step 3, the list is sorted by κv\kappa_v: entries with different values are in y-order, and entries with equal values form one block through one point, now in slope order (a block of size 1 is sorted).

Step 4. Before each insert the list is sorted by κv\kappa_v and its entries are in A(v)A(v), so their keys are distinct by Lemma 1. Line L2 finds the first position with a larger key, so all entries before it have a key less than or equal to κv(s)\kappa_v(s), and by Lemma 1 (applied to ss, which is in A(v)A(v) since x1(s)=v<x2(s)x_1(s) = v < x_2(s)) strictly less. Line L3 inserts ss there, and the list stays sorted by κv\kappa_v.

After step 4 the list holds the s∈A(u)s \in A(u) with x2(s)>vx_2(s) > v, which are the segments of A(v)A(v) with x1(s)<vx_1(s) < v (each of them has x1(s)≤ux_1(s) \le u because no segment starts in (u,v)(u, v)), together with the ss with x1(s)=vx_1(s) = v. That is A(v)A(v), sorted by κv\kappa_v.

Queries. ABOVE and BELOW read the entries next to the position that LOCATE returns, so they return the neighbors in κv\kappa_v order, which by Lemma 2 is the order along the line just to the right of vv. For NEIGHBORS-OF-POINT(T,y)(T, y), lines L15 and L16 are binary searches in the non-decreasing values: positions before lolo have value <y< y, positions from hihi on have value >y> y, and positions lolo to hi−1hi - 1 have value yy. So T[lo−1]T[lo - 1] is the highest stored segment strictly below (v,y)(v, y) and T[hi]T[hi] the lowest one strictly above, or NIL when there is none. □\square

Between events. The same argument with Lemma 3 shows that at each x′x' strictly between two events, the list is strictly increasing in ys(x′)y_s(x') and holds A(x′)A(x'), so SET-X to such a position followed by queries also gives the order along the line. ■\blacksquare

Back to Sweep status structure