求排列的逆序数 发表于 2018-12-25 分类于 algorithm 本文字数: 1.3k 阅读时长 ≈ 1 分钟 1234567891011121314151617181920总时间限制: 1000ms 内存限制: 65536kB 描述 在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她)对各种不同信息的兴趣,从而实现个性化的服务。对于不同的排名结果可以用逆序来评价它们之间的差异。考虑1,2,…,n的排列i1,i2,…,in,如果其中存在j,k,满足 j < k 且 ij > ik, 那么就称(ij,ik)是这个排列的一个逆序。一个排列含有逆序的个数称为这个排列的逆序数。例如排列 263451 含有8个逆序(2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),因此该排列的逆序数就是8。显然,由1,2,…,n 构成的所有n!个排列中,最小的逆序数是0,对应的排列就是1,2,…,n;最大的逆序数是n(n-1)/2,对应的排列就是n,(n-1),…,2,1。逆序数越大的排列与原始排列的差异度就越大。现给定1,2,…,n的一个排列,求它的逆序数。输入 第一行是一个整数n,表示该排列有n个数(n <= 100000)。 第二行是n个不同的正整数,之间以空格隔开,表示该排列。 输出 输出该排列的逆序数。 样例输入 6 2 6 3 4 5 1 样例输出 8 对于冒泡排序,交换次数就是逆序对数归并排序时,归并操作时统计左边数组中小于右边数组元素的个数。增加一句ans+=mid-i+1; 12345678910111213141516171819202122232425262728293031323334353637383940#include<iostream>#include<cstdio>#define N 100010using namespace std;int n,a[N],b[N];long long ans;void merge_sort(int l,int r){ if(l==r) return; int mid=(l+r)/2,i,j,k; i=l;k=l;j=mid+1; merge_sort(l,mid); merge_sort(mid+1,r); while(i<=mid && j<=r) { if(a[i]<=a[j]) b[k++]=a[i++]; else ans+=mid-i+1,b[k++]=a[j++]; } while(i<=mid) b[k++]=a[i++]; while(j<=r) b[k++]=a[j++]; for(int o=l;o<=r;++o) a[o]=b[o];}int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); merge_sort(1,n); for(int i=1;i<=n;++i) printf("%d ",a[i]); printf("\n%lld\n",ans); return 0;}