-
题目描述:
- 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
-
输入:
-
每个测试案例包括两行:第一行包含一个整数n,表示数组中的元素个数。其中1 <= n <= 10^5。第二行包含n个整数,每个数组均为int类型。
-
输出:
- 对应每个测试案例,输出一个整数,表示数组中的逆序对的总数。
-
样例输入:
-
4 7 5 6 4
-
样例输出:
-
5
-
思路;
-
可利用分治法,
-
第一步将问题划分两半,即将数组分成数目一样多的两半
-
第二步分别求出两边的逆序对数
-
第三部求出i在左边而j在右边的逆序对数
-
直接采用归并排序的算法,由于归并排序时从小到大进行的,当右边的input[j]复制到tmp中时,左边还没来得及复制到tmp中的那些数就是左边所有比input[j]大的数,只要在累加器中加上middle - start的值即可.
-
注意代码中区间为[start, end)
-
#include<stdio.h> long long findInversePairs(int* input, int start, int end, int* tmp, long long* count)//[start, end)返回类型 { if(input == NULL || start < 0 || end < 0 || tmp == NULL) return -1; if(end - start > 1) { int middle = start + (end - start)/2; int p = start, q = middle, i = start; findInversePairs(input, start, middle, tmp, count); findInversePairs(input, middle, end, tmp, count); while(p < middle || q < end) { if(q >= end || (p < middle && input[p] <= input[q]))// 少一个等于 { tmp[i++] = input[p++]; } else { tmp[i++] = input[q++]; *count += middle - p; } } for(i = start; i < end; ++i) { input[i] = tmp[i]; //错误的写法input[i++] = tmp[i++]; } } return *count; } int main() { int n; while(scanf("%d", &n) != EOF) { int* input = new int[n]; int* tmp = new int[n]; int i; for(i = 0; i < n; ++i) { scanf("%d", &input[i]); } long long count = 0;//int型不能够表达最大值,int型能表示最大的是多少 printf("%ld\n", findInversePairs(input, 0, n, tmp, &count));//注意是ld delete[] input; delete[] tmp; } return 0; } /************************************************************** Problem: 1348 User: oceaniwater Language: C++ Result: Accepted Time:100 ms Memory:1808 kb ****************************************************************/
-