Algorithm Search⌘K

Proofs: Segment tree

These are the human proofs of Segment tree, at full length.

The operations of a segment tree keep the node invariant and return the range product full

This proof shows: correctness, termination.

Let (S,⊕,e)(S, \oplus, e) be a monoid and let n≥1n \ge 1. For integers a,ba, b we write Π(a,b)=A[a]⊕A[a+1]⊕⋯⊕A[b]\Pi(a, b) = A[a] \oplus A[a+1] \oplus \cdots \oplus A[b] when a≤ba \le b, and Π(a,b)=e\Pi(a, b) = e when a>ba > b. By associativity, Π(a,b)\Pi(a, b) does not depend on the brackets, and for a≤m+1≤b+1a \le m + 1 \le b + 1,

Π(a,b)=Π(a,m)⊕Π(m+1,b).(1)\Pi(a, b) = \Pi(a, m) \oplus \Pi(m + 1, b). \tag{1}

For a≤ba \le b this is associativity; when one side is empty it is the identity law. The range of a node is the pair (lo,hi)(lo, hi) that the calls pass with it. The invariant is

(S) for each node vv of range (lo,hi)(lo, hi): T[v]=Π(lo,hi)T[v] = \Pi(lo, hi).

Lemma 0 (the calls are well formed). Each call BUILD(v,lo,hi)(v, lo, hi), QUERY(v,lo,hi,l,r)(v, lo, hi, l, r) or UPDATE(v,lo,hi,i,x)(v, lo, hi, i, x) that starts from (1,0,n−1)(1, 0, n - 1) has 0≤lo≤hi≤n−10 \le lo \le hi \le n - 1. If lo<hilo < hi, the two child ranges (lo,mid)(lo, mid) and (mid+1,hi)(mid + 1, hi) are nonempty, they are adjacent, their union is (lo,hi)(lo, hi), and each is shorter than (lo,hi)(lo, hi).

Proof. The first call has lo=0≤n−1=hilo = 0 \le n - 1 = hi. If lo<hilo < hi, then lo≤mid=⌊(lo+hi)/2⌋<hilo \le mid = \lfloor (lo + hi)/2 \rfloor < hi, so lo≤midlo \le mid and mid+1≤himid + 1 \le hi. Both child lengths, mid−lo+1mid - lo + 1 and hi−midhi - mid, are at least 1 and at most hi−lohi - lo. By induction on the depth of the call, every call has a nonempty range inside [0,n−1][0, n - 1]. □\square

Termination. Each recursive call is on a child range, whose length hi−lohi - lo is smaller by at least 1 than that of the caller, by Lemma 0. A call with hi−lo=0hi - lo = 0 makes no recursive call in BUILD (line L1) or UPDATE (line L10). In QUERY, a call with lo=hilo = hi returns in line L6 or line L7, since the single index lolo is either outside [l,r][l, r] or inside it. So every call ends.

Lemma 1 (build). After BUILD(v,lo,hi)(v, lo, hi), (S) holds for vv and for every node below vv.

Proof. By strong induction on k=hi−lok = hi - lo. If k=0k = 0, line L1 sets T[v]=A[lo]=Π(lo,lo)T[v] = A[lo] = \Pi(lo, lo), and vv has no node below it. If k≥1k \ge 1, lines L3 and L4 build the two children; their lengths are smaller, so by the induction hypothesis T[2v]=Π(lo,mid)T[2v] = \Pi(lo, mid) and T[2v+1]=Π(mid+1,hi)T[2v + 1] = \Pi(mid + 1, hi), and (S) holds below them. The two subtrees use disjoint node indices, because the indices below 2v2v start with the bits of 2v2v and those below 2v+12v + 1 start with the bits of 2v+12v + 1, so the second call does not change a cell that the first one set. Line L5 then sets T[v]=Π(lo,mid)⊕Π(mid+1,hi)=Π(lo,hi)T[v] = \Pi(lo, mid) \oplus \Pi(mid + 1, hi) = \Pi(lo, hi) by (1). □\square

Lemma 2 (query). Assume (S). Then QUERY(v,lo,hi,l,r)(v, lo, hi, l, r) returns Π(max⁡(l,lo),min⁡(r,hi))\Pi(\max(l, lo), \min(r, hi)), that is, the product of AA over [lo,hi]∩[l,r][lo, hi] \cap [l, r] in left to right order, and ee when the intersection is empty. It does not change TT.

Proof. By strong induction on k=hi−lok = hi - lo. Write a=max⁡(l,lo)a = \max(l, lo) and b=min⁡(r,hi)b = \min(r, hi).

  • If r<lor < lo or hi<lhi < l, the intersection is empty, so a>ba > b and the answer is ee, which line L6 returns.
  • Otherwise, if l≤lol \le lo and hi≤rhi \le r, then a=loa = lo and b=hib = hi, and line L7 returns T[v]=Π(lo,hi)T[v] = \Pi(lo, hi) by (S).
  • Otherwise lo<hilo < hi, since a range of one index is either disjoint from [l,r][l, r] or inside it. By Lemma 0 the children have shorter ranges, so by the induction hypothesis the two calls of line L9 return Π(max⁡(l,lo),min⁡(r,mid))\Pi(\max(l, lo), \min(r, mid)) and Π(max⁡(l,mid+1),min⁡(r,hi))\Pi(\max(l, mid + 1), \min(r, hi)). We show that their product is Π(a,b)\Pi(a, b). Let m=min⁡(max⁡(mid,a−1),b)m = \min(\max(mid, a - 1), b), the last index of the intersection that is at most midmid, or a−1a - 1 if there is none. The first value equals Π(a,m)\Pi(a, m) and the second equals Π(m+1,b)\Pi(m + 1, b): if a≤mida \le mid and b≥mid+1b \ge mid + 1, then m=midm = mid and both are clear; if b≤midb \le mid, then m=bm = b, the first value is Π(a,b)\Pi(a, b) and the second range is empty, so it gives e=Π(b+1,b)e = \Pi(b + 1, b); if a≥mid+1a \ge mid + 1, then m=a−1m = a - 1, the first range is empty and the second is Π(a,b)\Pi(a, b). In each case a≤m+1≤b+1a \le m + 1 \le b + 1, so by (1) the product of line L9 is Π(a,b)\Pi(a, b), with the left value first.

QUERY only reads TT. □\square

The top call QUERY(1,0,n−1,l,r)(1, 0, n - 1, l, r) with 0≤l≤r≤n−10 \le l \le r \le n - 1 therefore returns Π(l,r)=A[l]⊕⋯⊕A[r]\Pi(l, r) = A[l] \oplus \cdots \oplus A[r].

Lemma 3 (update). Assume (S) before UPDATE(1,0,n−1,i,x)(1, 0, n - 1, i, x) with 0≤i≤n−10 \le i \le n - 1, and let A′A' be AA with A′[i]=xA'[i] = x. Afterwards (S) holds for A′A'.

Proof. We show, by strong induction on k=hi−lok = hi - lo, that if lo≤i≤hilo \le i \le hi and (S) holds for AA at every node below vv and at vv, then after UPDATE(v,lo,hi,i,x)(v, lo, hi, i, x) the statement (S) holds for A′A' at vv and at every node below vv. If k=0k = 0, then lo=hi=ilo = hi = i and line L10 sets T[v]=x=A′[i]T[v] = x = A'[i]. If k≥1k \ge 1, then ii lies in exactly one child range, by Lemma 0: the left one when i≤midi \le mid and the right one otherwise, which is the test of lines L12 and L13. By the induction hypothesis, after the call that child and all nodes below it satisfy (S) for A′A'. The other child does not hold ii in its range, so its subtree satisfies (S) for AA, and AA and A′A' agree on its range, so it satisfies (S) for A′A' as well; the call did not touch its cells, because they lie in the other subtree. Line L14 sets T[v]=Π′(lo,mid)⊕Π′(mid+1,hi)=Π′(lo,hi)T[v] = \Pi'(lo, mid) \oplus \Pi'(mid + 1, hi) = \Pi'(lo, hi) by (1) for A′A'.

At the top call, every node of the tree is the root or below it. The nodes that the call does not reach have a range without ii, and they keep (S) by the same argument. □\square

Theorem. After BUILD(1,0,n−1)(1, 0, n - 1) and any sequence of updates, each query (l,r)(l, r) with 0≤l≤r≤n−10 \le l \le r \le n - 1 returns A[l]⊕⋯⊕A[r]A[l] \oplus \cdots \oplus A[r] for the current array, and every call ends.

Proof. Lemma 1 gives (S) after BUILD. Lemma 3 keeps (S) across each update, and Lemma 2 shows that a query does not change TT and returns the right value under (S). Termination was shown above. ■\blacksquare

Back to Segment tree