class Solution:
def countSmaller(self, A: List[int]) -> List[int]:
n = len(A)
res = [0] * n
B = []
for i, v in enumerate(A):
B.append((v,i))
def merge(l_arr, r_arr):
"""tc O(NlgN) sc O(N)
1. when both left array and right array is not running out, compare left[l] with right[r], move it onto merged array,
2. if right element move before left element, update state accumutate. otherwise, add offset onto final result array while append smaller to merged element
3. when one of the subarray run out, go through remaining array and append them onto merged array
4. update offset to final result array if it is left arrray that remains
"""
l, r, r2l = 0,0,0
merged_tmp = []
while l < len(l_arr) and r < len(r_arr):
if l_arr[l][0] > r_arr[r][0]:
merged_tmp.append(r_arr[r]) # note merged temporary array can't be inserted value only, need to be same format as input array
r2l += 1
r += 1
else:
merged_tmp.append(l_arr[l])
res[l_arr[l][1]] += r2l # right to left swap accumulative count
l += 1
while r < len(r_arr):
merged_tmp.append(r_arr[r])
r += 1
while l < len(l_arr):
merged_tmp.append(l_arr[l])
res[l_arr[l][1]] += r2l
l += 1
return merged_tmp # merged sorted subarray
def sort(A):
if len(A) == 1:
return A
mid = len(A)//2
left = sort(A[:mid])
right = sort(A[mid:])
return merge(left, right)
sort(B)
return res