📜  使用有序集和GNU C++ PBDS计算反转

📅  最后修改于: 2021-04-27 22:06:53             🧑  作者: Mango

给定N个整数的数组arr [] 。任务是找到反转数。如果arr [i]> arr [j]且i 两个元素arr [i]arr [j]构成一个反转。

例子

我们已经讨论了以下方法:

  • 计算数组中的反转设置1(使用合并排序)
  • 计算数组中的反转|设置2(使用自平衡BST)
  • 使用C++ STL中的Set计数反转
  • 计算数组中的反转|第3组(使用BIT)

在本文中,我们将讨论一种使用有序集和GNU C++ PBDS的方法。

方法:
我们将使用函数order_of_key(K) ,该函数在对数N时间内返回严格小于K的元素

  1. 将数组的第一个元素插入Ordered_Set中。
  2. 对于arr []中的所有其余元素,请执行以下操作:
    • 将当前元素插入Ordered_Set中。
    • 使用函数order_of_key(arr [i] +1)在Ordered_Set中找到严格小于当前元素+ 1的元素数。
    • Ordered_Set和order_of_key(current_element + 1)大小之间的差异将给出当前元素的反转计数。

    例如:

    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
    

下面是上述方法的实现:

// 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,
             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;
    // Intialise the ordered_set
    ordered_set set1;
  
    // Insert the first
    // element in set
    set1.insert(arr[0]);
  
    // Intialise 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;
}
输出:
6

时间复杂度: O(Nlog N)