- 以前做题的时候会遇到“已知一个数组,求经过冒泡排序之后排序为有序序列需要经过多少次交换”的问题,现在总结一下。
- 这个问题的核心是求逆序对个数,那么问题就转化为了求逆序对个数了
- 有很多种求逆序对个数的方法,这里记录一种归并排序的方法
例题代码如下
#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define LL long long
#define UIT unsigned int
#define DB double
#define PII pair<int, int>
#define MKPR(a, b) make_pair(a, b)
#define MMST(a) memset(a, 0, sizeof(a))
#define PB push_back
#define FOR(i, beg, ed, s) for (int i = beg; i < ed; i += s)
#define FORE(i, beg, ed, s) for (int i = beg; i <= ed; i += s)
#define LOOP while (true)
#define IN scanf
#define OUT printf
using namespace std;
const int N = 5e5 + 5;
int a[N], b[N];
LL ans;
void merge(int l, int r, int *a, int *b) {
int ptr = l;
int mid = l + (r - l) / 2;
int ll = mid;
while (l < mid && ll < r) {
if (a[l] <= a[ll]) {
b[ptr++] = a[l++];
} else {
b[ptr++] = a[ll++];
ans += mid - l;
}
}
while (l < mid) {
b[ptr++] = a[l++];
}
while (ll < r) {
b[ptr++] = a[ll++];
}
}
void merge_sort(int l, int r, int *a, int *b) {
if (r - l == 1) return;
int mid = l + (r - l) / 2;
merge_sort(l, mid, a, b);
merge_sort(mid, r, a, b);
merge(l, r, a, b);
for (int i = l; i < r; i++) {
a[i] = b[i];
}
}
void solve() {
int n;
while (~IN("%d", &n) && n) {
ans = 0;
FOR(i, 0, n, 1) { IN("%d", &a[i]); }
merge_sort(0, n, a, b);
OUT("%lld\n", ans);
}
}
int main(void) {
solve();
return 0;
}
- 归并排序不仅可以将数组以
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn) 的复杂度排好序,还可以求出原数组中的逆序对个数,特此记录。