求逆序数:
基本思路:归并排序,二分法;
所谓归并排序,即用递归对一个数组进行排序,归并排序分为拆分和合并两个过程,。以对一个数组升序为例,先递推将一个数组分为两个部分,从中间截开,一直分直到每个部分只剩一个数,然后开始递归合并,合并从两个只有一个数的部分开始,递归时不断将两个部分合成一个部分,在合成时要将小的数放在前面(以保证每次合成时的两个部分都是有序的),就这样一直合成直到回到原来要排序的数组,此时这个数组也是有序的,即这个数组升序,完成!举个栗子,比如说要将数组[5 2 4 7 8 1 3 2]升序,那么归并排序会将其分为[5],[2],[4],[7],[8],[1],[3],[2]几个部分,然后就合并:[2,5],[4,7],[1,8],[2,3],再一次合并:[2,4,5,7],[1,2,3,8],最后一次合并[1,2,2,3,4,5,7,8];可能不怎么好理解,直接看我写的函数
拆分:
void merge_sort(int a[], int left, int right) {//切开
if (left < right) {//拆分结束条件
int mid = (left + right) / 2;//从中间分开
merge_sort(a, left, mid); //把左边部分沿中间分开
merge_sort(a, mid + 1, right);//把右边部分沿中间分开
merge(a, left, right, mid);//合并
}
}
合并:
void merge(int a[], int left, int right, int mid) {//合并
int s[100];//一个新数组用来存储排序好的数组
int i = left, j = mid + 1;//两个变量分别指向左边和右边两组数的第一个数
int sor = left;
while (i <= mid && j <= right) {
if (a[i] < a[j]) {//归并的过程
s[sor++] = a[i++];
} else {
s[sor++] = a[j++];
}
}
while (i <= mid) s[sor++] = a[i++];//当一组数已经全部排进去之后,再将另外一组剩余数都排进去
while (j <= right)s[sor++] = a[j++];
sor = left;
while (sor <= right) {//把排好序的新数组全部放回原数组里
a[sor] = s[sor];
sor++;
}
}
回归正题,本题思路:
读题,如果一对数前后位置与大小顺序相反,即i>j且arr[i]<arr[j],则arr[i]与arr[j]被称为一对逆序数,由归并排序的核心思想,本题就很容易联想到归并排序,归并排序每一次合并都会拿有序的两个部分的第一个元素进行比较,如果前一个元素大于后一个元素,这不正是逆序数吗?那么我们可以从这里入手,不多废话,直接看代码:
#include<stdio.h>
int nu[109900], s[109900], re = 0; //nu存储输入的数,s存储每次合并的部分
void mm(int a[], int left, int right, int mid) {
int i = left, j = mid + 1;
int sor = left;
while (i <= mid && j <= right) {
if (a[i] > a[j]) {//如果前面的元素比后面大,即l ~ mid中的元素 > mid + 1 ~ r中的元素,逆序数出现
re += mid - i + 1;//由于l ~ mid和mid + 1 ~ r都是有序序列,故只要a[i]>a[j],那么a[i]~a[mid]就都会大于a[j],即逆序数总数就要加mid-i+1;
//切记,不是re++;
s[sor++] = a[j++];
} else {
s[sor++] = a[i++];
}
}
while (i <= mid) s[sor++] = a[i++];
while (j <= right)s[sor++] = a[j++];
sor = left;
while (sor <= right) {
a[sor] = s[sor];
sor++;
}
}
void msort(int a[], int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
msort(a, left, mid);
msort(a, mid + 1, right);
mm(a, left, right, mid);
}
}
int main() {
int T;
scanf("%d", &T);
getchar();
for (int i = 1; i <= T; i++) {
int num;
re = 0;
scanf("%d", &num);
for (int io = 0; io < num; io++) {
scanf("%d", &nu[io]);
}
msort(nu, 0, num - 1);
printf("%d\n", re);
}
return 0;
}
羊了,今天写不动了~~~~~