// solution 1: brute force
// for each element, count number of elements which are on right side of it and are smaller than it
int count_inversions(int A[], int N) {
int count = 0;
for(int i=0; i<N-1; i++) {
for(int j=i+1; j<N; j++) {
if(A[i] > A[j])
count++;
}
}
return count;
}
// solution 2: divide & conquer, similar to merge sort
int count_inversions(int A[], int i, int j) {
if(i >= j) return 0;
int m = (i+j)>>1;
int c1 = count_inversions(A, i, m);
int c2 = count_inversions(A, m+1, j);
int c3 = merge(A, B, i, m, j);
return c1 + c2 + c3;
}
/*
void merge_sort(int A[], int low, int high) {
if(low >= high) return;
int m = (low + high) >> 1;
merge_sort(A, low, m);
merge_sort(A, m+1, high);
merge(A, B, low, m, high);
}*/
int merge(int A[], int low, int m, int high) { // gist, add a mid parameter
// merge left and right half of A into B, then assign all items in B into A
// left half range: [low, m], right half range: [m+1, high]
int i = low, j = m+1, k = low;
int B[1000];
int total_inversions = 0;
while(i <= m && j <= high) {
if(A[i] < A[j])
B[k++] = A[i++];
else {
B[k++] = A[j++];
total_inversions += m - i + 1; // gist
}
}
while(i <= m) B[k++] = A[i++];
while(j <= high) B[k++] = A[j++];
k--; // no need?
for(int t=low; t<=high; t++) A[t] = B[t];
return total_inversions;
}