Algorithm Search⌘K

Proofs: Bentley's rectangle union sweep

These are the human proofs of Bentley's rectangle union sweep, at full length.

Bentley's sweep returns the area of the union of the rectangles full

This proof shows: correctness, termination.

We use the pseudocode of the page. The rectangles are Ri=[ai,bi]×[ci,di]R_i = [a_i, b_i] \times [c_i, d_i] with ai≤bia_i \le b_i and ci≤dic_i \le d_i, for i=1,…,ni = 1, \ldots, n. We write ∣A∣|A| for the length (one-dimensional Lebesgue measure) of a set A⊆RA \subseteq \mathbb{R} and μ\mu for the area. For a node uu with index range [lu,ru)[l_u, r_u), let Yu=[Y[lu],Y[ru]]Y_u = [Y[l_u], Y[r_u]] be its yy-range. The leaves are the elementary intervals, and the two children of a node split its index range in two non-empty parts. If n=0n = 0, the loop does not run and line L10 returns 0, which is correct. Assume n≥1n \ge 1.

Termination. The loop runs 2n2n times. Each UPDATE call either returns at line L11 or L12, or calls UPDATE on the two children of a node that is not a leaf. (A leaf uu has ru=lu+1r_u = l_u + 1, so it is either disjoint from [lo,hi)[lo, hi) or inside it, and it never reaches line L13.) The depth grows by one at each call, so the recursion stops at the leaves.

Canonical nodes. For 0≤lo≤hi≤m−10 \le lo \le hi \le m - 1, let C(lo,hi)C(lo, hi) be the set of nodes uu with [lu,ru)⊆[lo,hi)[l_u, r_u) \subseteq [lo, hi) whose parent range is not inside [lo,hi)[lo, hi) (or uu is the root). The ranges of the nodes of C(lo,hi)C(lo, hi) are pairwise disjoint, and their union is [lo,hi)[lo, hi): each index j∈[lo,hi)j \in [lo, hi) is in the leaf [j,j+1)[j, j+1), which is inside [lo,hi)[lo, hi), and the highest ancestor of that leaf whose range is inside [lo,hi)[lo, hi) is the unique node of C(lo,hi)C(lo, hi) that contains jj. So ⋃u∈C(lo,hi)Yu=[Y[lo],Y[hi]]\bigcup_{u \in C(lo, hi)} Y_u = [Y[lo], Y[hi]] when lo<hilo < hi.

Lemma 1. UPDATE(root,lo,hi,v)(root, lo, hi, v) changes cnt[u]cnt[u] by vv for each u∈C(lo,hi)u \in C(lo, hi) and for no other node. It changes lenlen only at the nodes on the paths from the root to the nodes of C(lo,hi)C(lo, hi).

Proof. By induction on the depth, a call UPDATE(u,lo,hi,v)(u, lo, hi, v) is made exactly for the nodes uu whose parent range meets [lo,hi)[lo, hi) but is not inside it (and for the root). For such a uu, line L11 returns if its range is disjoint from [lo,hi)[lo, hi); line L12 applies if its range is inside [lo,hi)[lo, hi), and then u∈C(lo,hi)u \in C(lo, hi) by definition; otherwise line L13 calls both children, which again have a parent that meets but is not inside [lo,hi)[lo, hi). Each node of C(lo,hi)C(lo, hi) has such a parent (or is the root), so it is reached, and line L12 runs there. Lines L14 to L16 run only at nodes that are called and do not return at line L11. A called node that returns at line L11 changes nothing. A called node that does not return meets [lo,hi)[lo, hi), so it is on a path from the root to a node of C(lo,hi)C(lo, hi). □\square

Lemma 2 (counts). Let tt be the moment just before the first event with coordinate xx is processed. Call rectangle ii active at tt if ai<x≤bia_i < x \le b_i. Then at tt, for each node uu, cnt[u]cnt[u] is the number of rectangles ii active at tt with ci<dic_i < d_i and u∈C(idx⁡(ci),idx⁡(di))u \in C(\operatorname{idx}(c_i), \operatorname{idx}(d_i)).

Proof. By Lemma 1 and induction over the events, cnt[u]cnt[u] is the sum, over the events processed so far, of vv if uu is in the set CC of the event's rectangle, and 0 otherwise. If ci=dic_i = d_i, the set CC is empty and rectangle ii adds nothing. At tt, the events processed so far are exactly those with coordinate less than xx, since line L3 sorts by xx. So rectangle ii with u∈Cu \in C adds +1+1 if ai<xa_i < x and −1-1 if bi<xb_i < x. Since ai≤bia_i \le b_i, it adds 1 if ai<x≤bia_i < x \le b_i and 0 otherwise. □\square

Between these moments, inside a group of events with the same xx, a count can be off (for example −1-1 when a rectangle with ai=bia_i = b_i has its −1-1 event sorted first). The proof uses the counts only at the moments of Lemma 2.

Lemma 3 (node invariant). After each event, for each node uu,

len[u]=∣⋃{ Yw:w in the subtree of u, cnt[w]>0 }∣.len[u] = \Big|\bigcup \{\, Y_w : w \text{ in the subtree of } u,\ cnt[w] > 0 \,\}\Big|.

Proof. Call the right side L(u)L(u). At the start all counts and lengths are 0, so both sides are 0. Assume the claim before an event. By Lemma 1 the event changes counts only at nodes of CC, and lines L14 to L16 run at each node on the paths from the root to those nodes, after the calls on its children. The value L(u)L(u) can change only if a count in the subtree of uu changes, and then uu is on one of those paths. So it is enough to show that lines L14 to L16 compute L(u)L(u) when the values of the children are already right. We check the three cases.

  • If cnt[u]>0cnt[u] > 0: YuY_u is in the union, and each YwY_w for ww below uu is inside YuY_u. So L(u)=∣Yu∣=Y[ru]−Y[lu]L(u) = |Y_u| = Y[r_u] - Y[l_u], as line L14 sets.
  • If cnt[u]=0cnt[u] = 0 and uu is a leaf: the union is empty, so L(u)=0L(u) = 0, as line L15 sets.
  • If cnt[u]=0cnt[u] = 0 and uu has children u1,u2u_1, u_2: the union is the union of the two unions for u1u_1 and u2u_2. These lie in Yu1Y_{u_1} and Yu2Y_{u_2}, which share at most one point. So L(u)=L(u1)+L(u2)=len[u1]+len[u2]L(u) = L(u_1) + L(u_2) = len[u_1] + len[u_2], as line L16 sets.

Nodes not on the paths keep both len[u]len[u] and L(u)L(u). □\square

Lemma 4 (covered length). At a moment tt of Lemma 2, len[root]=∣⋃i active at t[ci,di]∣len[root] = \big|\bigcup_{i \text{ active at } t} [c_i, d_i]\big|.

Proof. By Lemma 3, len[root]len[root] is the length of the union of YwY_w over the nodes with cnt[w]>0cnt[w] > 0. By Lemma 2, these are the nodes of C(idx⁡(ci),idx⁡(di))C(\operatorname{idx}(c_i), \operatorname{idx}(d_i)) for the active ii with ci<dic_i < d_i. For such ii, the union of these YwY_w is [ci,di][c_i, d_i]. An active ii with ci=dic_i = d_i adds a single point, of length 0. So both sides are the length of the same set, up to a finite set of points. □\square

Theorem. UNION-AREA returns μ(⋃i=1nRi)\mu\big(\bigcup_{i=1}^{n} R_i\big).

Proof. Let x1<x2<⋯<xsx_1 < x_2 < \cdots < x_s be the distinct values among all aia_i and bib_i.

Step 1: the area is a sum over strips. Let U=⋃iRiU = \bigcup_i R_i. Every point of UU has x1≤x≤xsx_1 \le x \le x_s. The vertical lines x=xkx = x_k have area 0. So μ(U)=∑k=1s−1μ(U∩Sk)\mu(U) = \sum_{k=1}^{s-1} \mu(U \cap S_k), with the open strip Sk=(xk,xk+1)×RS_k = (x_k, x_{k+1}) \times \mathbb{R}. For x∈(xk,xk+1)x \in (x_k, x_{k+1}), rectangle RiR_i meets the vertical line at xx if and only if ai≤x≤bia_i \le x \le b_i, which holds if and only if ai≤xka_i \le x_k and bi≥xk+1b_i \ge x_{k+1}, because no aia_i or bib_i lies strictly between xkx_k and xk+1x_{k+1}. Call this set of rectangles AkA_k; it does not depend on xx. The section of UU at xx is ⋃i∈Ak[ci,di]\bigcup_{i \in A_k} [c_i, d_i], of length ℓk\ell_k that does not depend on xx. By Fubini's theorem, μ(U∩Sk)=ℓk(xk+1−xk)\mu(U \cap S_k) = \ell_k (x_{k+1} - x_k).

Step 2: the loop adds these terms. Consider the events in sorted order. Within a group of events with the same xx, line L7 adds len[root]⋅0=0len[root] \cdot 0 = 0 for each event after the first, because prev=xprev = x already. At the first event of the group with x=xk+1x = x_{k+1}, prev=xkprev = x_k (the xx of the previous group), and line L7 adds len[root]⋅(xk+1−xk)len[root] \cdot (x_{k+1} - x_k), with len[root]len[root] read before this group changes anything. This is the moment tt of Lemma 2 for x=xk+1x = x_{k+1}. The rectangles active at tt have ai<xk+1≤bia_i < x_{k+1} \le b_i, that is ai≤xka_i \le x_k and bi≥xk+1b_i \ge x_{k+1}. This is AkA_k. By Lemma 4, len[root]=ℓklen[root] = \ell_k. At the first event, line L5 set prevprev to its xx, so line L7 adds 0.

So at the end, area=∑k=1s−1ℓk(xk+1−xk)=μ(U)area = \sum_{k=1}^{s-1} \ell_k (x_{k+1} - x_k) = \mu(U) by Step 1. ■\blacksquare

Back to Bentley's rectangle union sweep