Counting Inversions using Ordered Set and GNU C++ PBDS

• Difficulty Level : Medium
• Last Updated : 26 Jul, 2021

Given an array arr[] of N integers. The task is to find the number of inversion. Two elements arr[i] and arr[j] form an inversion if arr[i] > arr[j] and i < j

Examples

Input: arr[] = {8, 4, 2, 1}
Output:
Explanation:
Given array has six inversions:

• (8, 4): arr > arr and 0 < 1
• (8, 2): arr > arr and 0 < 2
• (8, 1): arr > arr and 0 < 3
• (4, 2): arr > arr and 1 < 2
• (4, 1): arr > arr and 1 < 3
• (2, 1): arr > arr and 2 < 3

Input: arr[] = {2, 3}
Output:
Explanation:
There is no such pair exists such that arr[i] > arr[j] and i < j.

We have already discussed below approaches:

In this post, we will be discussing an approach using Ordered Set and GNU C++ PBDS.

Approach:
We will be using the function order_of_key(K) which returns number of elements strictly smaller than K in log N time.

1. Insert the first element of the array in the Ordered_Set.
2. For all the remaining element in arr[] do the following:
• Insert the current element in the Ordered_Set.
• Find the number of element strictly less than current element + 1 in Ordered_Set using function order_of_key(arr[i]+1).
• The difference between size of Ordered_Set and order_of_key(current_element + 1) will given the inversion count for the current element.

For Example:

arr[] = {8, 4, 2, 1}
Ordered_Set S = {8}
For remaining element in arr[]:
At index 1, the element is  4
S = {4, 8}
key = order_of_key(5) = 1
The difference between size of S and key gives the total
number of inversion count for that current element.
inversion_count = S.size() - key =  2 - 1 = 1
Inversion Pairs are: (8, 4)

At index 2, the element is  2
S = {2, 4, 8}
key = order_of_key(3) = 1
inversion_count = S.size() - key =  3 - 1 = 2
Inversion Pairs are: (8, 2) and (4, 2)

At index 3, the element is 1
S = {1, 2, 4, 8}
key = order_of_key(2) = 1
inversion_count = S.size() - key =  4 - 1 = 3
Inversion Pairs are: (8, 1), (4, 1) and (2, 1)

Total inversion count = 1 + 2 + 3 = 6

Below is the implementation of the above approach:

C++

 // Ordered set in GNU C++ based// approach for inversion count#include #include #include using namespace __gnu_pbds;using namespace std; // Ordered Set Treetypedef tree,             rb_tree_tag,             tree_order_statistics_node_update>    ordered_set; // Returns inversion count in// arr[0..n-1]int getInvCount(int arr[], int n){    int key;    // Initialise the ordered_set    ordered_set set1;     // Insert the first    // element in set    set1.insert(arr);     // Initialise inversion    // count to zero    int invcount = 0;     // Finding the inversion    // count for current element    for (int i = 1; i < n; i++) {        set1.insert(arr[i]);         // Number of elements strictly        // less than arr[i]+1        key = set1.order_of_key(arr[i] + 1);         // Difference between set size        // and key will give the        // inversion count        invcount += set1.size() - key;    }    return invcount;} // Driver's Codeint main(){    int arr[] = { 8, 4, 2, 1 };    int n = sizeof(arr) / sizeof(int);     // Function call to count    // inversion    cout << getInvCount(arr, n);    return 0;}
Output:
6

Time Complexity: O(Nlog N)

My Personal Notes arrow_drop_up