def __init__
def __init__

Reputation: 1066

optimising count of inversion(i.e for i<j, a[i]>a[j]) for a large array

I am trying to count inversion(for eg.,for array [2,5,4,1] the inversion count is=4 namely (2,1),(5,4),(5,1),(4,1) using divide and conquer for a large set of arrays, I am getting a recursive count of value when a function executes each merge sort. I store all the count values in a vector and then again use sum operations, it works well for an array size of 70,000 but fails after it. I feel I am unnecessarily storing a large value to vector, instead, I am looking for a way to directly count the same but I am not getting a way to do the same, please help me in achieving it.

ps:the file link is this. my code looks like;

#include<iostream>
#include<vector>
#include<fstream>
using namespace std;
long long greater_v(long long *array,long long ap,long long p){
    long long numx=0;
    for(long long i=0;i<p;i++){
        if(array[i]>ap){
            numx++;
        }
    }
    return numx;
}
long long merge(long long U[],long long Lu,long long V[],long long Lv,long long S[],long long count1){
    long long uf=0;long long vf=0;
    for(long long sb=0;sb<Lu+Lv;sb++){
        if(uf<Lu && vf<Lv){
            if(U[uf]<V[vf]){
                S[sb]=U[uf];uf++;}
            else{
                S[sb]=V[vf];
               count1=count1+=greater_v(U,V[vf],Lu);
                
                vf++;
                

            }
        }
        else if(uf<Lu){
            S[sb]=U[uf];uf++;
        }
        else{
            S[sb]=V[vf];vf++;
        }
    }
return count1;
}

In this part I am looking for help where I am storing the value in the vector, instead, i want a way to directly count.

vector<unsigned long long int>v_val;
void MergeSort(long long arr[],long long n){
    long long count=0;
    //cout<<"sorting  ";print(arr,n);
    if(n==1)
        return;
    long long U[n/2];long long V[n-n/2];
    for(long long i=0;i<n/2;i++){
        U[i]=arr[i];
        }
    for(long long i=0;i<n-n/2;i++){
        V[i]=arr[i+n/2];
        }
    MergeSort(U,n/2);
    MergeSort(V,n-n/2);
    count+=merge(U,n/2,V,n-n/2,arr,count);
    v_val.push_back(count);
}

main function is;

int main(){
long long test_count=0;
    ifstream file_num("pr_as_2.txt");
    long long arr_num[100000];
    for(long long i=0;i<100000;i++){
        file_num>>arr_num[i];
    }


unsigned long long int sum_val=0;
   MergeSort(arr_num,70000);
   for(size_t i=0;i<v_val.size();i++){
       sum_val+=v_val[i];
   }
   cout<<sum_val;

}

Upvotes: 2

Views: 157

Answers (1)

Satya
Satya

Reputation: 153

look at this approach, it worked for me.

#include <bits/stdc++.h>

using namespace std;

// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
unsigned int merge(int arr[], int temp[], int l, int m, int r) {
    unsigned int inversions = 0;
    int i = l;
    int j = m;
    int k = l;
    while (i < m && j <= r) {
        if (arr[i] <= arr[j]) {
            temp[k] = arr[i];
            i++;
        } else {
            temp[k] = arr[j];
            j++;
            inversions += m-i;
        }
        k++;
    }
    while (i < m) {
        temp[k] = arr[i];
        i++;
        k++;
    }
    while (j <= r) {
        temp[k] = arr[j];
        j++;
        k++;
    }
    for (int i = l; i <= r; i++) {
        arr[i] = temp[i];
    }
    return inversions;
}

unsigned int count(int arr[], int temp[], int l, int r) {
    unsigned int inversions = 0;
    if (r > l) {
        int m = (r+l)/2;
        inversions = count(arr, temp, l, m);
        inversions += count(arr, temp, m+1, r);
        inversions += merge(arr, temp, l, m+1, r);
    }
    return inversions;
}

int main() {
    int arr_size = 100000;
    int arr[arr_size];
    ifstream file("IntegerArray.txt");
    string str;
    int i = 0;
    while (getline(file, str)) {
        arr[i] = stoi(str);
        i++;
    }
    // int arr[] = { 1, 20, 6, 4, 5 };
    // int arr_size = sizeof(arr) / sizeof(arr[0]);
    int temp[arr_size];
    /* mergeSort(arr, 0, arr_size-1);
    for (int i = 0; i < arr_size; i++) {
        cout << arr[i] << " ";
    } */
    cout << count(arr, temp, 0, arr_size-1) << endl;
}

Upvotes: 1

Related Questions