Algorithm Search⌘K

Proofs: Counting inversions with a Fenwick tree

These are the human proofs of Counting inversions with a Fenwick tree, at full length.

The Fenwick scan returns the number of inversions full

This proof shows: correctness, termination.

We use the pseudocode of the page, with the input A[1…n]A[1 \ldots n]. For q∈[1,n]q \in [1, n] let g(q)=∣{p<q:A[p]>A[q]}∣g(q) = |\{p < q : A[p] > A[q]\}|, the number of inversions with right end qq. Each inversion (p,q)(p, q) has exactly one right end, so

inv⁡(A)=∑q=1ng(q).(1)\operatorname{inv}(A) = \sum_{q=1}^{n} g(q). \tag{1}

Step 1: the ranks preserve order. Line L1 makes V=(v1<v2<⋯<vm)V = (v_1 < v_2 < \cdots < v_m), the distinct values of AA, and line L2 sets r[j]=tr[j] = t where vt=A[j]v_t = A[j]. Such a tt exists and is unique, because A[j]A[j] is one of the values and the vtv_t are distinct. For any p,qp, q, since vv is strictly increasing in tt, A[p]>A[q]A[p] > A[q] if and only if r[p]>r[q]r[p] > r[q], and A[p]=A[q]A[p] = A[q] if and only if r[p]=r[q]r[p] = r[q]. Also 1≤r[j]≤m1 \le r[j] \le m.

Step 2: the Fenwick tree lemma. Let f[1…m]f[1 \ldots m] be a frequency array, and say that TT represents ff when T[i]=∑v=i−lowbit⁡(i)+1if[v]T[i] = \sum_{v = i - \operatorname{lowbit}(i) + 1}^{i} f[v] for each i∈[1,m]i \in [1, m]. The Fenwick tree page proves, in its file proofs/correctness.md, that if TT represents ff, then PREFIX(T,i)(T, i) returns f[1]+⋯+f[i]f[1] + \cdots + f[i] for 0≤i≤m0 \le i \le m, and that after ADD(T,m,i,d)(T, m, i, d) with 1≤i≤m1 \le i \le m the array TT represents ff with f[i]f[i] increased by dd. Both loops terminate: PREFIX clears one set bit of ii at each step, so it stops after at most ⌊lg⁡m⌋+1\lfloor \lg m \rfloor + 1 steps, and ADD at least doubles lowbit⁡(i)≥1\operatorname{lowbit}(i) \ge 1 at each step, so ii exceeds mm after at most ⌊lg⁡m⌋+1\lfloor \lg m \rfloor + 1 steps.

Step 3: the invariant of the scan. For 1≤j≤n+11 \le j \le n + 1 let fj[v]=∣{p<j:r[p]=v}∣f_j[v] = |\{p < j : r[p] = v\}|. We show that the loop of line L4 keeps:

(S) Before the iteration for jj: TT represents fjf_j, and c=∑q<jg(q)c = \sum_{q < j} g(q).

Initialization. Line L3 sets TT to zeros and c=0c = 0. The array f1f_1 is all zeros, and an all-zero TT represents it, since each T[i]T[i] is a sum of zeros. The sum ∑q<1g(q)\sum_{q < 1} g(q) is empty. So (S) holds for j=1j = 1.

Maintenance. Assume (S) for some j≤nj \le n. By Step 2, PREFIX(T,r[j])(T, r[j]) returns

∑v≤r[j]fj[v]=∣{p<j:r[p]≤r[j]}∣=∣{p<j:A[p]≤A[j]}∣,\sum_{v \le r[j]} f_j[v] = |\{p < j : r[p] \le r[j]\}| = |\{p < j : A[p] \le A[j]\}|,

where the last equality is Step 1. There are j−1j - 1 indices p<jp < j, and each has either A[p]≤A[j]A[p] \le A[j] or A[p]>A[j]A[p] > A[j], but not both. So $(j - 1) - $ PREFIX(T,r[j])=∣{p<j:A[p]>A[j]}∣=g(j)(T, r[j]) = |\{p < j : A[p] > A[j]\}| = g(j), and after line L5, c=∑q≤jg(q)c = \sum_{q \le j} g(q). Line L6 calls ADD(T,m,r[j],1)(T, m, r[j], 1) with 1≤r[j]≤m1 \le r[j] \le m, so by Step 2 the array TT then represents fjf_j with fj[r[j]]f_j[r[j]] increased by 1, which is fj+1f_{j+1}. So (S) holds for j+1j + 1.

Termination. The loop of line L4 runs for j=1,…,nj = 1, \ldots, n and each iteration terminates by Step 2. After the last one, (S) holds for j=n+1j = n + 1, so c=∑q≤ng(q)c = \sum_{q \le n} g(q), which by (1) is inv⁡(A)\operatorname{inv}(A). Line L7 returns it. ■\blacksquare

The online property. The same invariant shows that after the iteration for jj, cc is ∑q≤jg(q)\sum_{q \le j} g(q), which is the inversion count of the prefix A[1…j]A[1 \ldots j], because an inversion of the prefix is an inversion (p,q)(p, q) of AA with q≤jq \le j.

Back to Counting inversions with a Fenwick tree