[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);
}
posted @ 2021-01-28 18:07  _dwt  阅读(21)  评论(0)    收藏  举报