poj(2299)——Ultra-QuickSort(归并排序求逆序数)

来源:互联网 发布:android性能优化工具 编辑:程序博客网 时间:2024/06/05 18:35

题意:

现在告诉你有n个数,然后你每次可以交换相邻两个序列中的数字,然后问你最少几次可以把这个序列变成一个递增的有序序列。

思路:

今天重新学习了一下归并排序,这个排序是增量的思想,但是又有点分治+递归。

至于怎样用归并来求逆序数的对数呢?我们把序列分成两半,然后如果后面那半的数小于前面那半的数的话,那么就说明在前面那个[p,mid)区间中有mid-p这么多的逆序数,因为归并排序保证了已经划分好的序列是有序的,余下的也是依次类推就好。

并且最好全部改成I64d的形式,要不然会WA。

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<vector>#include<algorithm>using namespace std;#define maxn 500050typedef __int64 ll;ll a[maxn],t[maxn],cnt=0;void merge_sort(ll x,ll y){if(y-x>1){ll mid=x+(y-x)/2;ll p=x,q=mid,i=x;merge_sort(x,mid);merge_sort(mid,y);while(p<mid||q<y){if(q>=y||(p<mid&&a[p]<=a[q])) t[i++]=a[p++];else t[i++]=a[q++],cnt+=mid-p;}for(ll j=x;j<y;j++) a[j]=t[j];}}int main(){ll n;while(~scanf("%I64d",&n)){if(n==0) break;memset(a,0,sizeof(a));memset(t,0,sizeof(t));cnt=0;for(int i=0;i<n;i++) scanf("%I64d",&a[i]);merge_sort(0,n);printf("%I64d\n",cnt);}}


0 0