题目链接:

https://www.luogu.com.cn/problem/P1908

题目大意:

给长为 n 的序列,求序列中逆序对的数目

思路:

一、
归并:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 5e5 + 10;
LL a[N], tmp[N], n, ans = 0;
void mergeSort(LL l, LL r){
	if (l >= r) return;
	LL mid = (l + r) >> 1, i = l, j = mid + 1, cnt = 0;
	mergeSort(l, mid);
	mergeSort(mid + 1, r);
	while (i <= mid || j <= r)
		if (j > r || (i <= mid && a[i] <= a[j]))
			tmp[cnt++] = a[i++];
		else
			tmp[cnt++] = a[j++], ans += mid - i + 1;
	for (LL k = 0; k < r - l + 1; k++)
		a[l + k] = tmp[k];
}
int main(){
	cin >> n;
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	mergeSort(1, n);
	cout << ans << "\n";
	return 0;
}

二、
树状数组:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
struct fwt{
	int n;
	vector <int> a;
	fwt(int n) : n(n), a(n + 1) {}
	LL sum(int x){
		LL res = 0;
		for (; x; x -= x & -x)
			res += a[x];
		return res;
	}
	void add(int x, LL k){
		for (; x <= n; x += x & -x)
			a[x] += k;
	}
	LL query(int x, int y){
		return sum(y) - sum(x - 1);
	}
};
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i ++ ){
		cin >> a[i];
	}
	auto b = a;
	sort(b.begin(), b.end());
	b.erase(unique(b.begin(), b.end()), b.end());
	for (int i = 0; i < n; i ++ ){
		int t = lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1;
		a[i] = t;
	}
	fwt f(n);
	LL ans = 0;
	for (int i = n - 1; i >= 0; i -- ){
		ans += f.query(1, a[i] - 1);
		f.add(a[i], 1);
	}
	cout << ans << "\n";
	return 0;
}
posted on 2022-01-13 16:31  Hamine  阅读(28)  评论(0编辑  收藏  举报