[NJUPSOJ]逆序对
description:
给定数组\(A_1,⋯,A_n\)。
定义逆序对为\((i,j)\),满足\(1\leqslant i<j\leqslant n,A_i>A_j\)。
求出逆序对的个数。
数据范围:\(1\leqslant n,A_i\leqslant 2×10^5\)
solution:
这个范围显然不能暴力\(\Theta(n^2)\)
在归并排序过程中, \(merge\)可以发现逆序, 记录每次调整减少的逆序数.
code:
#include<cstdio>
long long ans = 0;
void merge(int* arr,const int& l,const int& mid, const int& r) {
int* tmp = new int[r - l + 1];
int p1 = l, p2 = mid + 1,p=0;
while (p1 <= mid && p2 <= r) {
if (arr[p1] <= arr[p2])tmp[p++] = arr[p1++];
else tmp[p++] = arr[p2++], ans+=(mid-p1+1);
}
while (p1<=mid) tmp[p++] = arr[p1++];
while (p2<=r) tmp[p++] = arr[p2++];
for (int i = l; i <= r; i++)arr[i] = tmp[i - l];
delete[] tmp;
}
void merge_sort(int* arr,const int& l,const int& r) {
if (r <= l)return;
int mid = l + (r - l) / 2;
merge_sort(arr, l, mid);
merge_sort(arr, mid + 1, r);
merge(arr, l, mid, r);
}
int main() {
int N;
scanf("%d", &N);
int* A = new int[N];
for (int i = 0; i < N; i++)scanf("%d", A + i);
merge_sort(A, 0, N - 1);
printf("%lld\n", ans);
}