Let say I have array A and B ( always equal size) A = 5 4 2 1
B = 8 3 6 7
I am to insert elements from B in to A while keeping the relative order of A while minimising inversions.
So the answer would be 3 5 4 1 2 6 7 8 (7 inversions)
I have tried sorting B first then poping min(a[0] b[0]) into an array C but cases like A = 99999 1 2 3
B = 5 6 7 8
Gives the wrong 5 6 7 8 99999 1 2 3 (15 inversions)
When the correct is 99999 1 2 3 5 6 7 8 (7 inversions)
I am at a lost please help
Okay, this is an interesting question. My current solution works in O(nlog(n)).
The logic behind this solution can be found here.
However, since there was no implementation there, I've decided to place it here.
The overall logic relies on two things:
Now, onto the code:
#include <bits/stdc++.h>
using namespace std;
long long merge(vector<int>& v, int temp[], int left, int mid, int right) {
int i,j,k;
long long inv_count = 0;
i = left;
j = mid;
k = left;
while ((i <= mid - 1) && (j <= right)) {
if (v[i] <= v[j]) {
temp[k++] = v[i++];
} else {
temp[k++] = v[j++];
inv_count += mid - i;
}
}
while (i <= mid - 1)
temp[k++] = v[i++];
while (j <= right)
temp[k++] = v[j++];
for (i = left; i <= right; i++)
v[i] = temp[i];
return inv_count;
}
long long _mergeSort(vector<int>& v, int temp[], int left, int right) {
int mid;
long long inv_count = 0;
if (v.size() < 2) return 0;
if (right > left) {
mid = (right + left) / 2;
inv_count += _mergeSort(v, temp, left, mid);
inv_count += _mergeSort(v, temp, mid + 1, right);
inv_count += merge(v, temp, left, mid + 1, right);
}
return inv_count;
}
long long countInversionsInVector(vector<int>& v) {
int temp[v.size()];
return _mergeSort(v, temp, 0, v.size() - 1);
}
void solveHelper(vector<int> &a, int sa, int ea, vector<int>& b, int sb, int eb, vector<int>& I) {
if (sb >= eb) return;
int mb = (sb + eb) / 2;
int b_elem = b[mb];
vector<int> sliced_a(ea - sa + 1);
for (auto index = a.begin() + sa; index < a.begin() + ea; index++) {
sliced_a.push_back(*index);
}
long long invCount = 0;
for (long long i = sa; i < ea; i++) {
if (a[i] < b_elem) {
invCount += 1;
}
}
long long minInvCount = invCount;
int insertionIndex = sa;
for (int i = sa; i < ea; i++) {
if (a[i] < b[mb]){
invCount -= 1;
} else {
invCount += 1;
}
if (invCount < minInvCount) {
minInvCount = invCount;
insertionIndex = i + 1;
}
}
I[mb] = insertionIndex;
solveHelper(a, sa, insertionIndex, b, sb, mb, I);
solveHelper(a, insertionIndex, ea, b, mb + 1, eb, I);
return;
}
void mergeFinal(vector<int>& a, vector<int>& b, vector<int>& I, vector<int>& final) {
int index_a = 0;
int index_b = 0;
for (int i = 0; i < 2 * a.size(); i++) {
if (i == I[index_b] + index_b) {
final[i] = b[index_b];
index_b++;
} else {
final[i] = a[index_a];
index_a++;
}
}
}
long long solve(vector<int>& a, vector<int>& b) {
sort(b.begin(), b.end());
vector<int> I(b.size());
solveHelper(a, 0, a.size(), b, 0, b.size(), I);
vector<int> final(2*a.size());
mergeFinal(a, b, I, final);
return countInversionsInVector(final);
}
int main() {
int n;
ios_base::sync_with_stdio(false); // speed up reading input
cin >> n;
vector<int> a(n), b(n);
for(int i = 0; i < n; i++) {
cin >> a[i];
}
for(int i = 0; i < n; i++) {
cin >> b[i];
}
cout << solve(a, b) << "\n";
}