* 拓展:求逆序对数量
subject: 给定长度为n的数组(1≤n≤100000)(数列中的元素的取值范围 [1,1e9]),若i<j,a[i]>a[j],则为逆数对。
步骤: 1)确定分点:mid=(l+r)/2; 2)数列分为[l,mid]&[mid+1,r] ∴逆序对的出现分为三种情况:a.两数在[l.mid]内; b.两数在[mid+1,r]内; c.两区间各一数。 注:两区间内数的顺序与c情况无关,∴可以单独处理完a和b情况后递归排序,方便c的处理。 3)情况a,递归算左边; 4)右边排序; 5)情况b,递归算右边; 6)左边排序; 7)情况c,依次比较两数列的数,直到找到a[i]>a[j],则第一个数列中i后的数都>a[j], ∴ans+=mid-i+1;
eg. #include<stdio.h> long long q[100009], t[100009],ans; void merge_sort(long long q[],int l, int r) { int mid = (l + r) / 2,i=l,j=mid+1,k=0; while (l >= r)return; merge_sort(q,l, mid); merge_sort(q,mid + 1, r); while (i <=mid&&j<=r) { if (q[i] <= q[j]) { t[k++] = q[i++]; } else { t[k++] = q[j++]; ans+=(mid-i+1); } } while (i <= mid)t[k++] = q[i++]; while (j <= r)t[k++] = q[j++]; for (i = l, j = 0; i <= r; i++, j++) { q[i] = t[j]; } } int main() { int n,i; scanf("%d", &n); for (i = 0; i < n; i++) { scanf("%lld", &q[i]); } merge_sort(q,0, n - 1); printf("%lld", ans); return 0; }