/**
* 归并排序merge_sort 分治算法
* 1. 确定分界点 mid = l + r >> 1
* 2. 递归排序 left right
* 3. 归并 合二为一
*
* T(n) = nLog(N)
*
* 边界分析:
* 为什么不用 mid - 1 作为分隔线呢
即 merge_sort(q, l, mid - 1 ), merge_sort(q, mid, r)
因为 mid = l + r >> 1 是向下取整,mid 有可能取到 l (数组只有两个数时),造成无限划分
*/
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int tmp[N], a[N];
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
void merge_sort(int q[], int l, int r)
{
// 递归的终止情况
if (l >= r ) return ;
// 第一步: 分成子问题
int mid = l + r >> 1;
// 第二步: 递归处理子问题
merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
// 第三步:合并子问题
int k = 0 , i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++] = q[i ++];
else tmp[k ++] = q[j ++];
// 将q[i]q[j]比较完毕后的剩余的部分追加到 排好序的tmp最后
while( i <= mid) tmp[k ++] = q[i ++];
while( j <= r ) tmp[k ++] = q[j++];
for (int i = l, j = 0; i <= r; i ++, j++) q[i] = tmp[j];
}
int main()
{
IOS;
int n;
cin >> n ;
for (int i = 0 ; i < n ; i ++) cin >> a[i];
merge_sort(a, 0, n - 1);
for (int i = 0; i < n; i ++ ) cout << a[i] << ' ' ;
return 0;
}
求逆序对的数量:
/**
*
* 数据范围 为什么用long long 类型 :
* 会爆int
*
* 数的个数是 10的5次方
* 最多逆序对数量为
* 数值: n n-1 n-2 ...
* 逆序对 n-1 + n-2 + ... 1
* 逆序对总数量为: n(n-1)/2
*
* n = 10的5次方,那么 n(n-1)/2 约等于N平方
* = 10的十次方/2
* = 5 * 10的9次方 > int 的最大值
*
*
*/
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int q[N], tmp[N];
typedef long long LL;
#define IOS ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
LL merge_sort(int q[], int l, int r)
{
if (l >= r ) return 0;
LL mid = l + r >> 1;
// 三种逆序对的情况,
// 1. 左半部的逆序对的数量 : merge_sort(L, mid)
// 2. 右半部的逆序对的数量: merge_sort(mid + 1, r)
// 3. 当q[i] > q[j]时 ,q[i]后的数也严格大于q[j] 所以 [i, mid]的个数是 sj对应的逆序对的数量
// Sj = mid - i + 1 q[i]之前的数已经是严格小于q[j]的
LL res = merge_sort(q, l , mid ) + merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
{
if (q[i] <= q[j] ) tmp[k++] = q[i++];
else // q[i] > q[j]的情况:
{
res += mid - i + 1; //
tmp[k ++] = q[j ++];
}
}
while (i <= mid ) tmp[k ++] = q[i ++];
while (j <= r) tmp[k ++] = q[j++];
for (int i = l, j = 0; i <= r; i ++ , j ++) q[i] = tmp[j];
return res;
}
int main()
{
IOS;
cin >> n;
for (int i = 0 ; i < n; i++) cin >> q[i];
cout << merge_sort(q,0, n - 1) <<endl;
return 0;
}