1 问题
有一个排列A(元素无重复),经过一定步数的转换,转为排列B。交换A中第i个元素和第j个元素的代价为|i-j|。
输入:
n //元素个数
n个整数 //排列A
n个整数 //排列B
输出:
一个整数 //需要的代价
2 分析
求两个元素的逆序数,(如果大数在小数前面,则是一个逆序,4231逆序数为3+1+1=5),逆序数表示经过逆序数次转换可以转为有序数列,有序数列转为当前状态也需要逆序数步,所以求两个数列的逆序数,然后做差。
3 代码
#include <iostream>
#include <iterator>
using namespace std;
int merge(int* arr, int* brr, int left, int right) {
int r = 0;
int mid = left + (right - left) / 2;
int i = left;
int j = mid + 1;
int k = left;
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) //构不成逆序,按降序排列
brr[k++] = arr[j++];
else{ //可以构成逆序
brr[k++] = arr[i++];
r += right - j + 1; //j右边所有的数都可以构成逆序
}
}
while (i <= mid)
brr[k++] = arr[i++];
while (j <= right)
brr[k++] = arr[j++];
for (i = left; i <= right; i++)
arr[i] = brr[i];
return r;
}
int cmergesort(int* arr, int* brr, int left, int right) {
int r = 0;
if (left < right) {
int mid = left + (right - left) / 2;
r += cmergesort(arr, brr, left, mid);
r += cmergesort(arr, brr, mid + 1, right);
r += merge(arr, brr, left, right);
}
return r;
}
void test() {
int arr[6] = { 2,6,3,4,5,1 }; //1 4 1 1 1
//int arr[6] = { 6,5,4,3,2,1 };
//int brr[6];
//int s = cmergesort(arr, brr, 0, 5);
//cout << s << endl;
int n;
cin >> n;
int* arr = new int[n];
int* brr = new int[n];
int* crr = new int[n]; //临时数组
for (int i = 0; i < n; i++)
cin >> arr[i];
for (int i = 0; i < n; i++)
cin >> brr[i];
int s1 = cmergesort(arr, crr, 0, n - 1);
int s2 = cmergesort(brr, crr, 0, n - 1);
int r = 0;
if (s1 > s2)
r = s1 - s2;
else
r = s2 - s1;
delete[] arr;
delete[] brr;
delete[] crr;
cout << r << endl;
}
int main() {
test();
//system("pause");
return 0;
}