An inversion is a pair i < j with a[i] > a[j]: an out-of-order pair. Piggyback on merge sort: while merging two sorted halves, every time you pull from the right half, it jumps ahead of all remaining left elements.
Split, recurse, then merge two sorted halves. When the right element is smaller than the current left element, it's smaller than every remaining left element too, so add (mid - i + 1) inversions at once.
long long mergeCount(vector<int>& a, int lo, int mid, int hi) {
vector<int> tmp; tmp.reserve(hi - lo + 1);
int i = lo, j = mid + 1;
long long inv = 0;
while (i <= mid && j <= hi) {
if (a[i] <= a[j]) tmp.push_back(a[i++]);
else {
tmp.push_back(a[j++]);
inv += (mid - i + 1); // a[i..mid] all > a[j]
}
}
while (i <= mid) tmp.push_back(a[i++]);
while (j <= hi) tmp.push_back(a[j++]);
for (int k = 0; k < tmp.size(); k++) a[lo + k] = tmp[k];
return inv;
}
long long countInv(vector<int>& a, int lo, int hi) {
if (lo >= hi) return 0;
int mid = (lo + hi) / 2;
return countInv(a, lo, mid) // left
+ countInv(a, mid + 1, hi) // right
+ mergeCount(a, lo, mid, hi); // cross
}
Merge sort's recursion tree: log n levels, O(n) work per level.
The temporary buffer used during each merge.
Checking all pairs. The merge trick is the big win.
inv += mid - i + 1. Because both halves are sorted, one right-element beating a[i] beats everything from i to mid in one shot.a[i] <= a[j] (not <) so equal elements aren't miscounted as inversions.n(n-1)/2, use 64-bit.