题目描述:
给一个序列,我们使用冒泡排序法对它进行排序。请输出在排序过程中会进行多少次交换。
Input
多组读入,以n = 0结尾,该组数据不需要处理。
第一行给一个n(n < 5e5)
接下来n行有n个数a[1]~a[n],代表该序列。
(0 <= a[i] < 1e9 )
Output
输出交换次数。
思路:
题目很容易让我们直接用冒泡排序做,但是数据量很大,会直接TE,利用归并排序做。
原理:
在判断 ”治“ 的时候判断符合大于时:cnt += mid - pl + 1
来个简单的理解一下4,3,2,1,用归并排序,
第一层
4大3,cnt = 0-0+1;2大1,cnt = 1+2-2+1=2;
|3,4| |1,2|
第二层
3大2,cnt = 2+1-0+1 = 4;3大1,cnt = 4+1-0+1 = 6;为什么不在考虑4呢,因为3大1就相当考虑4了
代码:
#include <iostream>
#include <cstdio>
using namespace std;
int n, a[500005], tmpA[500005];
long long cnt;
void merge_sort(int l, int r, int *A)
{
if (l >= r) return ;
int mid = l+(r-l)/2;
merge_sort(l, mid, A);
merge_sort(mid + 1, r, A);
int pl = l, pr = mid + 1, tmpp = 0;
while(pl <= mid && pr <= r)
{
if (A[pl] <= A[pr])
tmpA[tmpp++] = A[pl++];
else
tmpA[tmpp++] = A[pr++], cnt += mid - pl + 1;
}
while(pl <= mid)
tmpA[tmpp++] = A[pl++];
while(pr <= r)
tmpA[tmpp++] = A[pr++];
for (int i = 0; i < tmpp; i++)
A[i + l] = tmpA[i];
}
int main()
{
while(scanf("%d", &n)&&n)
{
cnt = 0;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
merge_sort(1, n, a);
printf("%lld\n", cnt);
}
return 0;
}