通过此题理解了所谓的分治, 挺简单的,具体思路就是先二分一样分数组, 后在合并的过程中排序,(本体用到了逆序数)合并的过程就是
将两个数组中的数合并多一个数组中去, 使其有序。(其中设置最大值的岗哨十分重要)具体合并代码如下:
for(int k = l; k <= r; k++)
if(left1[i] < right1[j]){
num[k] = left1[i++];
}else {
ans += n1 - i + 1;
num[k] = right1[j++];
}
if(left1[i] < right1[j]){
num[k] = left1[i++];
}else {
ans += n1 - i + 1;
num[k] = right1[j++];
}
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int M = 500010;
int left1[M];
int right1[M];
int num[M];
__int64 ans;
int n;
void mergesum(int *num, int l, int mid, int r) {
int n1 = mid - l + 1;
int n2 = r - mid;
for(int i = 1; i <= n1; i++)
left1[i] = num[l+i -1];
for(int i = 1; i <= n2; i++)
right1[i] = num[mid+i];
left1[n1+1] = 1e9; //两个岗哨的设置十分重要, 不然会出现溢出现象。
right1[n2+1] = 1e9;
int i = 1, j = 1;
for(int k = l; k <= r; k++)
if(left1[i] < right1[j]){
num[k] = left1[i++];
}else {
ans += n1 - i + 1;
num[k] = right1[j++];
}
}
void mergesort(int *num, int l, int r) {
if(l < r) {
int mid = (r + l)/2;
mergesort(num, l, mid); //进行分治操作。
mergesort(num, mid + 1, r);
mergesum(num, l, mid, r); //进行合并操作。
}
}
int main()
{
while(scanf("%d", &n) != EOF) {
if(!n)
break;
for(int i = 1; i <= n; i++)
scanf("%d", &num[i]);
ans = 0;
mergesort(num, 1, n);
for(int i = 1; i <= n; i++)
printf("%d ", num[i]);
printf("\n");
printf("%I64d\n", ans);
}
return 0;
}