数组中的反转次数.使用归并排序

Number of Inversion Count in an array. Using Merge Sort

本文关键字:归并排序 数组      更新时间:2023-10-16

对于那些不知道反转的人。

反演-

给定一个包含N个整数的数组A,数组的反转定义为任意一对索引(i,j),使得i <j和A[i]> A[j].

总之:

{inv}(A) = {(A(i),A(j)), i A(j)}

例如,数组a={2,3,1,5,4}对于(2,1),(3,1),(5,4)的元素对有三种反转:(1,3),(2,3),(4,5)。

总倒置计数= 3.

嗯,我试着用标准归并排序来解决这个问题。以下是我认为它是如何工作的。

假设在某个阶段,partA和partb的归并排序是

partA -[1, 2, 3]。

partB -(4、5)

现在,设X为第一个数组partA的元素。Y =第二个数组partB.

如果X被复制到输出数组(i。e if X

Else如果Y被复制到输出数组(i。e(如果X> Y)。然后我们得到反转计数= count + mid - i+1。(i是该元素的位置)。因为它是按递增顺序排序的,所以位置j> i, X[j]> y的所有元素

下面是代码的进一步细节。

#include <iostream>
#include <vector>
using namespace std;
vector<int> a;
vector<int> c;
void merge(int low, int high, int mid);
void mergesort(int low, int high)
{
 int mid;
 if (low < high)
 {
     mid=(low+high)/2;
     mergesort(low,mid);
     mergesort(mid+1,high);
     merge(low,high,mid);
 }
return ;
}
int count ; //to store the inversion count
void merge(int low, int high, int mid)
{
int i, j, k;
i = low;
k = low;
j = mid + 1;
// standard merging from merge sort
while (i <= mid && j <= high)
{
    if (a[i] < a[j])
    {
        c[k] = a[i];
        k++;
        i++;
    }
    else
    {
        c[k] = a[j];
        k++;
         j++;
      //   cout<<a[i]<<" "<<mid<<" "<<i<<"n";
         count += mid - i+1; // This is where the trick occurs, if X > Y,
         //eg. in [3, 4, 5] and [1,2]
         //if(3>1) then 4,5 is obviously greater then 1, thus making count as mid - i+1              
     }
 }
while (i <= mid)
{
    c[k] = a[i];
    k++;
    i++;
}
while (j <= high)
{
    c[k] = a[j];
    k++;
    j++;
}
for (i = low; i < k; i++)
{
    a[i] = c[i];
 }
}
int main()
{
//int a[20], i, b[20];
int T;
cin>>T;
while(T--){
    //cout<<"enter  the elementsn";
    int N;
    cin>>N;
    count =0;
    a.clear(); a.resize(N);
    c.clear(); c.resize(N);
    for (int i = 0; i < N; i++)
    {
        cin>>a[i];
    }
    mergesort(0, N-1);
    cout<<count<<"n";
}
}

好,现在来看看我的疑问,我相信上面实现的逻辑是合法的,足以解决反转的数量,但由于一些奇怪的原因,它不是,我不确定是什么导致了这里的WA。

我被困在这个问题上有一段时间了,没能弄清楚。这不是家庭作业问题,只是我认为逻辑没有问题,代码仍然不起作用,可能的原因是什么?救命! .

Ideone Link - https://ideone.com/nmvl7i

关于Spoj的问题- http://www.spoj.com/problems/INVCNT/

注意:前两个测试用例工作得很好,当提交时我得到了WA。

您的解决方案的问题是结果可能大于整数范围,例如,如果序列为n, n - 1,…, 1,(不增加)反转次数将为n*(n - 1)/2,当n = 2*10^5时,结果将远远大于整数范围。

int count改为long long count

改变这一行:

count += mid - i + 1;

为:

count += (long long)mid - (long long) i + 1L;

你将得到接受的答案。

我接受的代码