Intuition
Checking every pair is O(n²). Merge sort already compares the left half against the right half while sorting — piggyback on it. When both halves are sorted, for each left element the right-half values that violate the condition form a prefix, so a two-pointer sweep counts all cross pairs in linear time per level.
Count-inversions with a twist — the condition nums[i] > 2 nums[j] isn't the same as the merge comparison, so the counting can't ride along inside the merge itself. It needs its own two-pointer sweep over the two sorted halves before* merging. Recognising when a counting condition diverges from the sort order is what tells you to separate the passes.
Approach
Divide
Split the array in half; count pairs entirely inside each half recursively. What's left is pairs that cross the middle.
Count cross pairs on sorted halves
With both halves sorted, walk a pointer j over the right half for each left i: advance j while nums[i] > 2*nums[j]. j never moves backward, so the count for the whole level is O(n).
Merge as usual
After counting, restore sorted order so the parent call sees a sorted range. The code delegates this to Python's sorted(): because the two halves are already sorted, Timsort detects the runs and merges them in linear time, so the level stays O(n) — an explicit two-pointer merge would be equivalent. Sorting doesn't lose pairs, since counting happened before the order changed across the boundary.
Solution & live demo
Common pitfalls
Counting inside the merge comparison
if left[i] <= right[j]:
merged.append(left[i]); i += 1
else:
count += len(left) - ij = mid
for i in range(lo, mid):
while j < hi and nums[i] > 2 * nums[j]: j += 1
count += j - midThat counts pairs where left[i] > right[j], not where left[i] > 2 * right[j] — a strictly different and much larger set. The doubled condition needs a separate sweep before the halves are merged.
Resetting the right pointer for each left element
for i in range(lo, mid):
j = mid
while j < hi and nums[i] > 2 * nums[j]: j += 1j = mid
for i in range(lo, mid):
while j < hi and nums[i] > 2 * nums[j]: j += 1Both halves are sorted, so a larger nums[i] can only push j further right — it never moves back. Resetting makes the sweep O(n²) per merge instead of O(n).
Counting after sorting the range
nums[lo:hi] = sorted(nums[lo:hi]) # then count
# count across the two sorted halves nums[lo:hi] = sorted(nums[lo:hi])
Once the range is merged, the split between left and right is gone and you can no longer tell which element came from which half — only cross-half pairs count as reverse pairs. Count first, merge second.
Edge cases
2*nums[j] handles signs fine; comparisons stay valid on sorted halves.
2× a large int needs 64 bits; Python is safe.