#include<cstdio> #define REP(i, a, b) for(int i = (a); i < (b); i++) using namespace std; const int MAXN = 112; int a[MAXN], n; void merge_sort(int l, int r) //这里是左闭右开区间, 区间分两段不需要加一减一 { if(l + 1 >= r) return; int m = (l + r) / 2; // l与r的平均数 merge_sort(l, m); merge_sort(m, r); //先递归, 再求解 int p = l, q = m, i = l, t[MAXN]; while(p < m || q < r) { if(q >= r || p < m && a[p] <= a[q]) t[i++] = a[p++]; //右区间空或者左区间非空且a[p]更优的时候加入 else t[i++] = a[q++]; } REP(i, l, r) a[i] = t[i]; } int main() { scanf("%d", &n); REP(i, 0, n) scanf("%d", &a[i]); merge_sort(0, n); REP(i, 0, n) printf("%d ", a[i]); puts(""); return 0; }
逆序对满足两个条件, i < j 和 ai > aj
归并可以求逆序对, 因为是按顺序加入, 所以右区间加入的时候, 左区间的数满足 i < j, 然后左边还没有加入的数肯定比当前的a[q]要大, 应该是按大小加入的, 所以满足ai >aj, 所以这个时候计数器可以加上左区间还没加入数的个数, 即m-p, 注意是左闭右开区间, 所以m-p不用加一。
//逆序对版本 #include<cstdio> #define REP(i, a, b) for(int i = (a); i < (b); i++) using namespace std; const int MAXN = 112; int a[MAXN], n, cnt; //如果多组数据cnt记得清0 void merge_sort(int l, int r) { if(l + 1 >= r) return; int m = (l + r) / 2; merge_sort(l, m); merge_sort(m, r); int p = l, q = m, i = l, t[MAXN]; while(p < m || q < r) { if(q >= r || p < m && a[p] <= a[q]) t[i++] = a[p++]; else t[i++] = a[q++], cnt += m - p; //加这一句话就行了 } REP(i, l, r) a[i] = t[i]; } int main() { scanf("%d", &n); REP(i, 0, n) scanf("%d", &a[i]); merge_sort(0, n); REP(i, 0, n) printf("%d ", a[i]); printf("\n%d\n", cnt); return 0; }