题目大意:给出n个数字,在只能两两交换的情况下,要经过多少次才能得到
递增序列
思路:首先,明确的一点是
一个数组的逆序数=两两交换的情况下得到递增序列的交换次数
举例如下:
一组数列 9,1,0,5,4
9 的逆序数是0
1 的逆序数是1
5 的逆序数是1
4 的逆序数是2
得到 0+1+1+2=5 恰好等于冒泡排序得到的结果
其次必须了解相关的归并排序的含义:
归并排序是将给出的数组,利用二分法不断二分化,然后再进行合并排序的方法。
利用二分法求逆序数快捷方便。
以下是代码:
#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <limits.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <functional>
using namespace std;
#define inf 1000000000 //10E
#define N 500050 //数组大小
__int64 t; //定义此类型 足以存放
void compute(int* s,int top,int mid,int end) //合并函数
{
int le=mid+1-top,ri=end-mid;
int left[N/2],right[N/2];
int i,j;
for(i=1;i<=le;i++)
left[i]=s[top+i-1];
for(j=1;j<=ri;j++)
right[j]=s[mid+j];
left[le+1]=right[ri+1]=inf;
i=j=1;
for(int k=top;k<=end;) //进行合并
{
if(left[i]<=right[j])
s[k++]=left[i++];
else
{
s[k++]=right[j++];
t+=le+1-i; //计算逆序数
}
}
return ;
}
void mergesort(int* s,int top,int end) //二分
{
if(top<end)
{
int mid=(top+end)/2;
mergesort(s,top,mid);
mergesort(s,mid+1,end);
compute(s,top,mid,end);
}
return ;
}
int main()
{
int n,i;
int* data=new int[N];
while(scanf("%d",&n)&&n)
{
t=0;
for(i=1;i<=n;i++)
scanf("%d",&data[i]);
mergesort(data,1,n);
printf("%I64d\n",t);
}
delete data;
return 0;
}
值得注意的是 在c++中传输指针的时候 ,必须将数组定义成指针的形式,并且在使用
之后删除。否则,会造成直接传输指针错误,直接结束程序。