逆序对

来源:互联网 发布:高级的数据分析算法 编辑:程序博客网 时间:2024/04/27 18:30

Time Limit: 2 Seconds      Memory Limit: 65536 KB

现在给定一个有 N 个数的数列 Ai。若对于 i < j,有 Ai > Aj,则称 (i, j) 为数列的一个逆序对。

例如,<2, 3, 8, 6, 1> 有五个逆序对,分别是 (1, 5), (2, 5), (3, 4), (3, 5), (4, 5)

现在请你求出一个给定数列的逆序对个数。

提示:排序算法可以解决这个问题。

输入格式

一个整数 T,表示有多少组测试数据。

每组测试数据第一行是一个正整数 N (1 <= N <= 100000),表示数列中有 N 个数字。

接下来一行包含 N 个正整数,代表对应的数列。

保证所有正整数小于 100000000。

输出格式

对于每组数据,输出一行,表示逆序对的个数。

样例输入

152 3 8 6 1

样例输出

5
思路: 归并排序求逆序数。合并排序在合并阶段分为两个序列(设L[]与R[]),L序列与R序列分别是经过排序的。每次从两个序列中取值时分两种情况:(1)从L中取值,这样取出的值的逆序数为0;(2)从R中取值,这时,取出的值的逆序数为L中剩余元素的个数。
#include <stdio.h>int arrTmp[100010];      long long num;void Merge(int arr[], int low, int mid, int high){int i = low, j = mid + 1, k = low;   while (i <= mid&&j <= high){if (arr[i] <= arr[j]){arrTmp[k++] = arr[i++];}else{arrTmp[k++] = arr[j++];num += mid - i + 1;}}while (i <= mid){arrTmp[k++] = arr[i++];}while (j <= high){arrTmp[k++] = arr[j++];}for (i = low; i <= high; i++){arr[i] = arrTmp[i];}}void MergeSort(int arr[], int low, int high){if (low<high){int mid = (low + high) / 2;MergeSort(arr, low, mid);MergeSort(arr, mid + 1, high);Merge(arr, low, mid, high);}}int main(){int T;while (scanf("%d", &T) != EOF){for (int i = 0; i<T; i++){int N;num = 0;scanf("%d", &N);int arr[100000];for (int j = 0; j<N; j++){scanf("%d", &arr[j]);}MergeSort(arr, 0, N - 1);printf("%lld\n", num);}}}



0 0
原创粉丝点击