-
Notifications
You must be signed in to change notification settings - Fork 1
/
inversions.py
67 lines (51 loc) · 1.6 KB
/
inversions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Number of Inversions
# Author: jerrybelmonte
import sys
def get_number_of_inversions(seq: list, arr: list, left: int, right: int):
"""
Counts the number of inversions of a given sequence.
:param seq: sequence of numbers
:param arr: array filled with zeros
:param left: starting index
:param right: ending index
:return: number of inversions
Example: there are two inversions: (a1, a3) 3 > 2, and (a2, a3) 9 > 2
>>> get_number_of_inversions([2, 3, 9, 2, 9], [0, 0, 0, 0, 0], 0, 5)
2
"""
num_inversions = 0
if right - left <= 1:
return num_inversions
mid = (left + right)//2
num_inversions += get_number_of_inversions(seq, arr, left, mid)
num_inversions += get_number_of_inversions(seq, arr, mid, right)
num_inversions += merge(seq, arr, left, mid, right)
return num_inversions
def merge(seq, arr, left, mid, right):
i, k, j = left, left, mid
inversion_count = 0
while i < mid and j < right:
if seq[i] <= seq[j]: # non-decreasing
arr[k] = seq[i]
k += 1
i += 1
else: # inversion detected
arr[k] = seq[j]
j += 1
k += 1
inversion_count += mid - i
while i < mid:
arr[k] = seq[i]
i += 1
k += 1
while j < right:
arr[k] = seq[j]
j += 1
k += 1
for ndx in range(left, right):
seq[ndx] = arr[ndx]
return inversion_count
if __name__ == '__main__':
n, *a = list(map(int, sys.stdin.read().split()))
b = n * [0]
print(get_number_of_inversions(a, b, 0, n))