 Open in App
Not now

# Counting Inversions using Ordered Set and GNU C++ PBDS

• Difficulty Level : Medium
• Last Updated : 22 Mar, 2022

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 give 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 Tree``typedef` `tree<``int``, null_type, less_equal<``int``>,``             ``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 Code``int` `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