📜  使用段树计算数组中的反转

📅  最后修改于: 2021-04-17 11:31:10             🧑  作者: Mango

给定一个整数数组arr ,任务是计算该数组中的求反数。
如果A [i]> A [j]且i 例子:

方法:

  • 构建一个细分树,其中每个节点将代表该节点范围内的总数。
  • 假设任何节点的范围是[i,j],则该节点将包含大于或等于i且小于或等于j的数量的计数。
  • 叶节点将仅为1或0,因为该节点的范围将为1。
  • 遍历数组,令索引i处的数字为a [i]。我们将发现段树中[a [i] +1,max]范围内存在多少个数字,其中max是数组的最大元素,并将其添加到answer变量中。
  • 然后,我们将该数字插入段树中,并继续到数组的最后一个索引。这样,对于每个元素,我们将添加出现在该元素之前且大于该元素的数字,即它们形成一个反转对。

下面是上述方法的实现:

C++
// C++ program to count the inversions
// present in the array using segment tree
#include "algorithm"
#include "cstring"
#include "iostream"
using namespace std;
 
// Function to update segment tree
// i.e. to insert the element
void update(int* Tree, int index, int s, int e, int num)
{
    // Leaf node condition
    if (s == num and e == num) {
        Tree[index] = 1;
        return;
    }
 
    // No overlap condition
    if (num < s or num > e) {
        return;
    }
 
    // Else call on both the children nodes
    int mid = (s + e) >> 1;
    update(Tree, 2 * index, s, mid, num);
    update(Tree, 2 * index + 1, mid + 1, e, num);
 
    Tree[index] = Tree[2 * index] + Tree[2 * index + 1];
}
 
// Function to count the total numbers
// present in the range [a[i]+1, mx]
int query(int* Tree, int index, int s,
          int e, int qs, int qe)
{
    // Complete overlap
    if (qs <= s and e <= qe) {
        return Tree[index];
    }
 
    // No Overlap
    if (s > qe or e < qs) {
        return 0;
    }
 
    int mid = (s + e) >> 1;
 
    return query(Tree, 2 * index, s,
                 mid, qs, qe)
           + query(Tree, 2 * index + 1,
                   mid + 1, e, qs, qe);
}
 
// Driver code
int main(int argc, char const* argv[])
{
    int arr[] = { 8, 4, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Maximum element present in the array.
    int mx = *max_element(arr, arr + n);
 
    // Segment Tree
    int Tree[6 * mx];
 
    // Initialize every node
    // of segment tree to 0
    memset(Tree, 0, sizeof(Tree));
 
    int answer = 0;
 
    for (int i = 0; i < n; ++i) {
 
        // add the count of inversion pair
        // formed with the element a[i] and the
        // elements appearing before the index i.
        answer += query(Tree, 1, 1, mx, arr[i] + 1, mx);
 
        // Insert the a[i] in the segment tree
        update(Tree, 1, 1, mx, arr[i]);
    }
 
    cout << answer;
    return 0;
}


Java
// Java program to count the inversions
// present in the array using segment tree
import java.io.*;
import java.util.Arrays;
class GFG
{
 
  // Function to update segment tree
  // i.e. to insert the element
  static void update(int[] Tree, int index,
                     int s, int e, int num)
  {
 
    // Leaf node condition
    if (s == num && e == num)
    {
      Tree[index] = 1;
      return;
    }
 
    // No overlap condition
    if (num < s || num > e)
    {
      return;
    }
 
    // Else call on both the children nodes
    int mid = (s + e) >> 1;
    update(Tree, 2 * index, s, mid, num);
    update(Tree, 2 * index + 1, mid + 1, e, num);
 
    Tree[index] = Tree[2 * index] + Tree[2 * index + 1];
  }
 
  // Function to count the total numbers
  // present in the range [a[i]+1, mx]
  static int query(int[] Tree, int index, int s,
                   int e, int qs, int qe)
  {
    // Complete overlap
    if (qs <= s && e <= qe)
    {
      return Tree[index];
    }
 
    // No Overlap
    if (s > qe || e < qs)
    {
      return 0;
    }
    int mid = (s + e) >> 1;
    return query(Tree, 2 * index, s, mid, qs, qe) +
      query(Tree, 2 * index + 1, mid + 1, e, qs, qe);
  }
 
  // Driver code
  public static void main (String[] args)
  {
    int arr[] = { 8, 4, 2, 1 };
    int n = arr.length;
 
    // Maximum element present in the array.
    int mx = Arrays.stream(arr).max().getAsInt();
 
    // Segment Tree
    int[] Tree = new int[6 * mx];
    int answer = 0;
    for (int i = 0; i < n; ++i)
    {
 
      // add the count of inversion pair
      // formed with the element a[i] and the
      // elements appearing before the index i.
      answer += query(Tree, 1, 1, mx, arr[i] + 1, mx);
 
      // Insert the a[i] in the segment tree
      update(Tree, 1, 1, mx, arr[i]);
    }   
    System.out.println(answer);
  }
}
 
// This code is contributed by rag2127


Python3
# Python3 program to count the inversions
# present in the array using segment tree
 
# Function to update segment tree
# i.e. to insert the element
def update(Tree, index, s, e, num):
     
    # Leaf node condition
    if (s == num and e == num):
        Tree[index] = 1
        return
 
    # No overlap condition
    if (num < s or num > e):
        return
 
    # Else call on both the children nodes
    mid = (s + e) >> 1
    update(Tree, 2 * index, s, mid, num)
    update(Tree, 2 * index + 1, mid + 1, e, num)
 
    Tree[index] = Tree[2 * index] + Tree[2 * index + 1]
 
# Function to count the total numbers
# present in the range [a[i]+1, mx]
def query(Tree,index, s,e, qs, qe):
     
    # Complete overlap
    if (qs <= s and e <= qe):
        return Tree[index]
 
    # No Overlap
    if (s > qe or e < qs):
        return 0
 
    mid = (s + e) >> 1
 
    return query(Tree, 2 * index, s,mid, qs, qe) +\
           query(Tree, 2 * index + 1, mid + 1, e, qs, qe)
 
# Driver code
if __name__ == '__main__':
    arr = [8, 4, 2, 1]
    n = len(arr)
 
    # Maximum element present in the array.
    mx = max(arr)
 
    # Segment Tree
    Tree = [0] * (6 * mx)
 
    # Initialize every node
    # of segment tree to 0
    answer = 0
 
    for i in range(n):
 
        # add the count of inversion pair
        # formed with the element a[i] and the
        # elements appearing before the index i.
        answer += query(Tree, 1, 1, mx, arr[i] + 1, mx)
 
        # Insert the a[i] in the segment tree
        update(Tree, 1, 1, mx, arr[i])
 
    print(answer)
 
# This code is contributed by Mohit Kumar


C#
using System;
using System.Linq;
 
class GFG
{
 
  // Function to update segment tree
  // i.e. to insert the element
  static void update(int[] Tree, int index,
                     int s, int e, int num)
  {
 
    // Leaf node condition
    if (s == num && e == num)
    {
      Tree[index] = 1;
      return;
    }
 
    // No overlap condition
    if (num < s || num > e)
    {
      return;
    }
 
    // Else call on both the children nodes
    int mid = (s + e) >> 1;
    update(Tree, 2 * index, s, mid, num);
    update(Tree, 2 * index + 1, mid + 1, e, num); 
    Tree[index] = Tree[2 * index] + Tree[2 * index + 1];
  }
 
  // Function to count the total numbers
  // present in the range [a[i]+1, mx]
  static int query(int[] Tree, int index,
                   int s, int e, int qs, int qe)
  {
 
    // Complete overlap
    if (qs <= s && e <= qe)
    {
      return Tree[index];
    }
 
    // No Overlap
    if (s > qe || e < qs)
    {
      return 0;
    }
    int mid = (s + e) >> 1;
    return query(Tree, 2 * index, s, mid, qs, qe) +
      query(Tree, 2 * index + 1, mid + 1, e, qs, qe);
  }
 
 
  // Driver code
  static public void Main ()
  {
    int[] arr = { 8, 4, 2, 1 };
    int n = arr.Length;
 
    // Maximum element present in the array.
    int mx =  arr.Max();
 
    // Segment Tree
    int[] Tree = new int[6 * mx];
    int answer = 0;
    for (int i = 0; i < n; ++i)
    {
 
      // add the count of inversion pair
      // formed with the element a[i] and the
      // elements appearing before the index i.
      answer += query(Tree, 1, 1, mx, arr[i] + 1, mx);
 
      // Insert the a[i] in the segment tree
      update(Tree, 1, 1, mx, arr[i]);
    }  
    Console.WriteLine(answer);
  }
}
 
// This code is contributed by avanitrachhadiya2155


输出:
6