📜  计算给定大小的所有子数组中的反转

📅  最后修改于: 2022-05-13 01:57:52.629000             🧑  作者: Mango

计算给定大小的所有子数组中的反转

给定一个数组和一个整数 k,计算所有大小为 k 的子数组中的所有反转。
例子:

Input : a[] = {7, 3, 2, 4, 1}, 
        k = 3;
Output : 6
Explanation: subarrays of size 3 are - 
{7, 3, 2}
{3, 2, 4}
{2, 4, 1} 
and there inversion count are 3, 1, 2 
respectively. So, total number of 
inversions are  6.

强烈建议使用 BIT 引用数组中的反转计数
计数反转的过程与上面链接的文章中的相同。首先,我们使用 BIT 计算数组中前 k 个(给定子数组的大小)元素的反转。现在,对于每个下一个子数组,我们减去前一个子数组的第一个元素的反转,并添加不包含在前一个子数组中的下一个元素的反转。重复此过程,直到处理完最后一个子数组。在上面的例子中,这个算法的工作原理是这样的——

a[] = {7, 3, 2, 4, 1}, 
  k = 3;

Inversion are counted for first subarray 
A = {7, 3, 2} Let this be equal to invcount_A.

For counting the inversion of subarray B we 
subtract the inversion of first element of A,
from invcount_A and add inversions of 4 (last 
element of B) in the subarray B.
So, invcount_B = invcount_A - 2 + 0
               = 3 - 2 + 0
               = 1

Same process is repeated for next subarray
and sum of all inversion count is the answer.  

C++
// C++ program to count inversions in all sub arrays
// of size k using Binary Indexed Tree
#include 
using namespace std;
 
// Returns sum of arr[0..index]. This function assumes
// that the array is preprocessed and partial sums of
// array elements are stored in BITree[].
int getSum(int BITree[], int index)
{
    int sum = 0; // Initialize result
 
    // Traverse ancestors of BITree[index]
    while (index > 0) {
        // Add current element of BITree to sum
        sum += BITree[index];
 
        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}
 
// Updates a node in Binary Index Tree (BITree) at
// given index in BITree.  The given value 'val' is
// added to BITree[i] and all of its ancestors in
// tree.
void updateBIT(int BITree[], int n, int index, int val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n) {
        // Add 'val' to current node of BI Tree
        BITree[index] += val;
 
        // Update index to that of parent
        // in update View
        index += index & (-index);
    }
}
 
// Converts an array to an array with values from 1 to n
// and relative order of smaller and greater elements
// remains same.  For example, {7, -90, 100, 1} is
// converted to {3, 1, 4, 2 }
void convert(int arr[], int n)
{
    // Create a copy of arrp[] in temp and sort
    // the temp array in increasing order
    int temp[n];
    for (int i = 0; i < n; i++)
        temp[i] = arr[i];
    sort(temp, temp + n);
 
    // Traverse all array elements
    for (int i = 0; i < n; i++) {
 
        // lower_bound() Returns pointer to
        //  the first element greater than
        // or equal to arr[i]
        arr[i] = lower_bound(temp, temp + n,
                         arr[i]) - temp + 1;
    }
}
 
// Returns inversion count of all subarray
// of size k in arr[0..n-1]
int getInvCount(int arr[], int k, int n)
{
    int invcount = 0; // Initialize result
 
    // Convert arr[] to an array with values from
    // 1 to n and relative order of smaller and
    // greater elements remains same.  For example,
    // {7, -90, 100, 1} is converted to {3, 1, 4, 2 }
    convert(arr, n);
 
    // Create a BIT with size equal to maxElement+1
    // (Extra one is used so that elements can be
    // directly be used as index)
    int BIT[n + 1];
    for (int i = 1; i <= n; i++)
        BIT[i] = 0;
 
    // Get inversion count of first subarray
    for (int i = k - 1; i >= 0; i--) {
 
        // Get count of elements smaller than arr[i]
        invcount += getSum(BIT, arr[i] - 1);
 
        // Add current element to BIT
        updateBIT(BIT, n, arr[i], 1);
    }
 
    // now calculate the inversion of all other subarrays
    int ans = invcount;
    int i = 0, j = k, icnt = 0, jcnt = 0;
    while (j <= n - 1) {
 
        // calculate value of inversion count of first element
        // in previous subarray
        icnt = getSum(BIT, arr[i] - 1);
        updateBIT(BIT, n, arr[i], -1);
 
        // calculating inversion count of last element in the
        // current subarray
        jcnt = getSum(BIT, n) - getSum(BIT, arr[j]);
        updateBIT(BIT, n, arr[j], 1);
 
        // calculating inversion count of current subarray
        invcount = invcount - icnt + jcnt;
 
        // adding current inversion to the answer
        ans = ans + invcount;
        i++, j++;
    }
    return ans;
}
int main()
{
    int arr[] = { 7, 3, 2, 4, 1 };
    int k = 3;
    int n = sizeof(arr) / sizeof(int);
    cout << "Number of inversions in all "
         "subarrays of size " << k <<" are : "
         << getInvCount(arr, k, n);
    return 0;
}


Java
// Java program to count inversions in all sub arrays
// of size k using Binary Indexed Tree
import java.util.*;
 
class GFG
{
 
// Returns sum of arr[0..index]. This function assumes
// that the array is preprocessed and partial sums of
// array elements are stored in BITree[].
static int getSum(int BITree[], int index)
{
    int sum = 0; // Initialize result
 
    // Traverse ancestors of BITree[index]
    while (index > 0)
    {
         
        // Add current element of BITree to sum
        sum += BITree[index];
 
        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}
 
// Updates a node in Binary Index Tree (BITree) at
// given index in BITree. The given value 'val' is
// added to BITree[i] and all of its ancestors in
// tree.
static void updateBIT(int BITree[], int n,
                      int index, int val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n)
    {
        // Add 'val' to current node of BI Tree
        BITree[index] += val;
 
        // Update index to that of parent
        // in update View
        index += index & (-index);
    }
}
 
// Converts an array to an array with values
// from 1 to n and relative order of smaller
// and greater elements remains same.
// For example, {7, -90, 100, 1} is
// converted to {3, 1, 4, 2 }
static void convert(int arr[], int n)
{
    // Create a copy of arrp[] in temp and sort
    // the temp array in increasing order
    int []temp = new int[n];
    for (int i = 0; i < n; i++)
        temp[i] = arr[i];
    Arrays.sort(temp);
 
    // Traverse all array elements
    for (int i = 0; i < n; i++)
    {
 
        // lower_bound() Returns pointer to
        // the first element greater than
        // or equal to arr[i]
        arr[i] = lower_bound(temp, 0, n,
                             arr[i]) + 1;
    }
}
 
static int lower_bound(int[] a, int low,
                       int high, int element)
{
    while(low < high)
    {
        int middle = low + (high - low) / 2;
        if(element > a[middle])
            low = middle + 1;
        else
            high = middle;
    }
    return low;
}
 
// Returns inversion count of all subarray
// of size k in arr[0..n-1]
static int getInvCount(int arr[], int k, int n)
{
    int invcount = 0; // Initialize result
 
    // Convert arr[] to an array with values from
    // 1 to n and relative order of smaller and
    // greater elements remains same. For example,
    // {7, -90, 100, 1} is converted to {3, 1, 4, 2 }
    convert(arr, n);
 
    // Create a BIT with size equal to maxElement+1
    // (Extra one is used so that elements can be
    // directly be used as index)
    int []BIT = new int[n + 1];
    for (int i = 1; i <= n; i++)
        BIT[i] = 0;
 
    // Get inversion count of first subarray
    for (int i = k - 1; i >= 0; i--)
    {
 
        // Get count of elements smaller than arr[i]
        invcount += getSum(BIT, arr[i] - 1);
 
        // Add current element to BIT
        updateBIT(BIT, n, arr[i], 1);
    }
 
    // now calculate the inversion of
    // all other subarrays
    int ans = invcount;
    int i = 0, j = k, icnt = 0, jcnt = 0;
    while (j <= n - 1)
    {
 
        // calculate value of inversion count of
        // first element in previous subarray
        icnt = getSum(BIT, arr[i] - 1);
        updateBIT(BIT, n, arr[i], -1);
 
        // calculating inversion count of
        // last element in the current subarray
        jcnt = getSum(BIT, n) - getSum(BIT, arr[j]);
        updateBIT(BIT, n, arr[j], 1);
 
        // calculating inversion count
        // of current subarray
        invcount = invcount - icnt + jcnt;
 
        // adding current inversion to the answer
        ans = ans + invcount;
        i++; j++;
    }
    return ans;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 7, 3, 2, 4, 1 };
    int k = 3;
    int n = arr.length;
    System.out.println("Number of inversions in all " +
                       "subarrays of size " + k +
                       " are : " + getInvCount(arr, k, n));
    }
}
 
// This code is contributed by PrinciRaj1992


Python3
# Python3 program to count inversions in all sub arrays
# of size k using Binary Indexed Tree
from bisect import bisect_left as lower_bound
 
# Returns sum of arr[0..index]. This function assumes
# that the array is preprocessed and partial sums of
# array elements are stored in BITree.
def getSum(BITree, index):
 
    sum = 0 # Initialize result
 
    # Traverse ancestors of BITree[index]
    while (index > 0):
     
        # Add current element of BITree to sum
        sum += BITree[index]
 
        # Move index to parent node in getSum View
        index -= index & (-index)
 
    return sum
 
# Updates a node in Binary Index Tree (BITree) at
# given index in BITree. The given value 'val' is
# added to BITree[i] and all of its ancestors in
# tree.
def updateBIT(BITree, n, index, val):
 
    # Traverse all ancestors and add 'val'
    while (index <= n):
        # Add 'val' to current node of BI Tree
        BITree[index] += val
 
        # Update index to that of parent
        # in update View
        index += index & (-index)
 
# Converts an array to an array with values from 1 to n
# and relative order of smaller and greater elements
# remains same. For example,7, -90, 100, 1 is
# converted to3, 1, 4, 2
def convert(arr, n):
 
    # Create a copy of arrp in temp and sort
    # the temp array in increasing order
    temp = [0]*(n)
    for i in range(n):
        temp[i] = arr[i]
    temp = sorted(temp)
 
    # Traverse all array elements
    for i in range(n):
 
        # lower_bound() Returns pointer to
        # the first element greater than
        # or equal to arr[i]
        arr[i] = lower_bound(temp, arr[i]) + 1
 
# Returns inversion count of all subarray
# of size k in arr[0..n-1]
def getInvCount(arr, k, n):
 
    invcount = 0 # Initialize result
 
    # Convert arr to an array with values from
    # 1 to n and relative order of smaller and
    # greater elements remains same. For example,
    # 7, -90, 100, 1 is converted to3, 1, 4, 2
    convert(arr, n)
 
    # Create a BIT with size equal to maxElement+1
    # (Extra one is used so that elements can be
    # directly be used as index)
    BIT=[0]*(n + 1)
    for i in range(1, n + 1):
        BIT[i] = 0
 
    # Get inversion count of first subarray
    for i in range(k - 1, -1, -1):
 
        # Get count of elements smaller than arr[i]
        invcount += getSum(BIT, arr[i] - 1)
 
        # Add current element to BIT
        updateBIT(BIT, n, arr[i], 1)
 
    # now calculate the inversion of all other subarrays
    ans = invcount
    i = 0
    j = k
    icnt = 0
    jcnt = 0
    while (j <= n - 1):
 
        # calculate value of inversion count of first element
        # in previous subarray
        icnt = getSum(BIT, arr[i] - 1)
        updateBIT(BIT, n, arr[i], -1)
 
        # calculating inversion count of last element in the
        # current subarray
        jcnt = getSum(BIT, n) - getSum(BIT, arr[j])
        updateBIT(BIT, n, arr[j], 1)
 
        # calculating inversion count of current subarray
        invcount = invcount - icnt + jcnt
 
        # adding current inversion to the answer
        ans = ans + invcount
        i += 1
        j += 1
 
    return ans
 
# Driver code
if __name__ == '__main__':
    arr= [7, 3, 2, 4, 1]
    k = 3
    n = len(arr)
    print("Number of inversions in all subarrays of size "
            ,k," are : ",getInvCount(arr, k, n))
 
# This code is contributed by mohit kumar 29


C#
// C# program to count inversions in all sub arrays
// of size k using Binary Indexed Tree
using System;
 
class GFG
{
     
// Returns sum of arr[0..index]. This function assumes
// that the array is preprocessed and partial sums of
// array elements are stored in BITree[].
static int getSum(int []BITree, int index)
{
    int sum = 0; // Initialize result
 
    // Traverse ancestors of BITree[index]
    while (index > 0)
    {
         
        // Add current element of BITree to sum
        sum += BITree[index];
 
        // Move index to parent node in getSum View
        index -= index & (-index);
    }
    return sum;
}
 
// Updates a node in Binary Index Tree (BITree) at
// given index in BITree. The given value 'val' is
// added to BITree[i] and all of its ancestors in
// tree.
static void updateBIT(int []BITree, int n,
                      int index, int val)
{
    // Traverse all ancestors and add 'val'
    while (index <= n)
    {
        // Add 'val' to current node of BI Tree
        BITree[index] += val;
 
        // Update index to that of parent
        // in update View
        index += index & (-index);
    }
}
 
// Converts an array to an array with values
// from 1 to n and relative order of smaller
// and greater elements remains same.
// For example, {7, -90, 100, 1} is
// converted to {3, 1, 4, 2 }
static void convert(int []arr, int n)
{
    // Create a copy of arrp[] in temp and sort
    // the temp array in increasing order
    int []temp = new int[n];
    for (int i = 0; i < n; i++)
        temp[i] = arr[i];
    Array.Sort(temp);
 
    // Traverse all array elements
    for (int i = 0; i < n; i++)
    {
 
        // lower_bound() Returns pointer to
        // the first element greater than
        // or equal to arr[i]
        arr[i] = lower_bound(temp, 0, n,
                             arr[i]) + 1;
    }
}
 
static int lower_bound(int[] a, int low,
                       int high, int element)
{
    while(low < high)
    {
        int middle = low + (high - low) / 2;
        if(element > a[middle])
            low = middle + 1;
        else
            high = middle;
    }
    return low;
}
 
// Returns inversion count of all subarray
// of size k in arr[0..n-1]
static int getInvCount(int []arr, int k, int n)
{
    int invcount = 0; // Initialize result
 
    // Convert arr[] to an array with values from
    // 1 to n and relative order of smaller and
    // greater elements remains same. For example,
    // {7, -90, 100, 1} is converted to {3, 1, 4, 2 }
    convert(arr, n);
 
    // Create a BIT with size equal to maxElement+1
    // (Extra one is used so that elements can be
    // directly be used as index)
    int []BIT = new int[n + 1];
    for (int i = 1; i <= n; i++)
        BIT[i] = 0;
 
    // Get inversion count of first subarray
    for (int i = k - 1; i >= 0; i--)
    {
 
        // Get count of elements smaller than arr[i]
        invcount += getSum(BIT, arr[i] - 1);
 
        // Add current element to BIT
        updateBIT(BIT, n, arr[i], 1);
    }
 
    // now calculate the inversion of
    // all other subarrays
    int ans = invcount;
    int x = 0, j = k, icnt = 0, jcnt = 0;
    while (j <= n - 1)
    {
 
        // calculate value of inversion count of
        // first element in previous subarray
        icnt = getSum(BIT, arr[x] - 1);
        updateBIT(BIT, n, arr[x], -1);
 
        // calculating inversion count of
        // last element in the current subarray
        jcnt = getSum(BIT, n) - getSum(BIT, arr[j]);
        updateBIT(BIT, n, arr[j], 1);
 
        // calculating inversion count
        // of current subarray
        invcount = invcount - icnt + jcnt;
 
        // adding current inversion to the answer
        ans = ans + invcount;
        x++; j++;
    }
    return ans;
}
 
// Driver Code
static public void Main ()
{
    int []arr = { 7, 3, 2, 4, 1 };
    int k = 3;
    int n = arr.Length;
    Console.Write("Number of inversions in all " +
                  "subarrays of size " + k +
                  " are : " + getInvCount(arr, k, n));
}
}
 
// This code is contributed by ajit.


Javascript


输出:

Number of inversions in all subarrays of size 3 are : 6