归并排序求逆序对
2018-05-30 22:22
169 查看
【题目描述】
现给定1,2,…,n的一个排列,求它的逆序数。
【输入格式】
第一行是一个整数n,表示该排列有n个数(n <= 100000)。
第二行是n个不同的正整数,之间以空格隔开,表示该排列。
【输出格式】
输出该排列的逆序数。
【分析】
(1)将区间[1..n]进行二分,先求出区间[1,mid]和[mid+1,n],而子区间又进行二分直到区间内只有一个元素。
(2)将已经排好序的子区间进行合并,即用有序的[L,K][K+1,R]求出有序的区间[L,R]最终合并成区间[1,N],而合并区间分为若干步:
①令i=j,j=mid+1,变量k=L,执行下一步。
②如果i<=mid,且j<=r,若a[i]<a[j],则令c[sum]=a[i],i++,sum++;
若a[i]>=a[j],则令c[sum]=a[j],j++,sum++,执行下一步,如果i>k,或j>r,则把令一个区间的剩下元素都放到c数组中,执行下一步。
③如果sum>r,则跳出循环。
求逆序对:在合并区间的第二步中在a[i]<a[j]中ans+=mid-i+1就可以了,说明a[j]比区间[i,mid]中的任何一个元素都要小,而且位置又在j的前面,提供了mid-i+1个逆序对。
【代码】
#include<bits/stdc++.h> using namespace std; typedef long long LL; int a[100010],c[100010]; int n; LL ans=0; void merge_sort(int l,int r){ int mid=(l+r)>>1,i=l,j=mid+1,k; if(l>=r)return; merge_sort(l,mid); merge_sort(mid+1,r); k=l; while(i<=mid&&j<=r){ if(a[i]>a[j]){ c[k++]=a[j++]; ans+=mid-i+1; } else c[k++]=a[i++]; } while(i<=mid)c[k++]=a[i++]; while(j<=r)c[k++]=a[j++]; for(i=l;i<=r;i++) a[i]=c[i]; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); merge_sort(1,n); printf("%lld\n",ans); return 0; }
相关文章推荐
- 【BZOJ4769】超级贞鱼 归并排序求逆序对
- 数据结构实验之排序五:归并求逆序数
- 数据结构实验之排序五:归并求逆序数
- 数据结构实验之排序五:归并求逆序数
- 数据结构实验之排序五:归并求逆序数
- HiHoCoder-第三十九周--二分·归并排序之逆序对
- 数组中的逆序对(归并排序思想解题)
- 链表的各种操作实现 链表逆序 链表排序 有序链表归并 链表存在环的判定
- poj-2299-逆序数-归并排序
- [luogu]P1966火柴排队-逆序对与归并排序的初步运用
- 求逆序数----归并排序的实质
- 数据结构实验之排序五:归并求逆序数
- SDUT OJ 3402数据结构实验之排序五:归并求逆序数
- poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】
- 数据结构实验之排序五:归并求逆序数
- 求逆序对 --- 归并排序水题
- 数据结构实验之排序五:归并求逆序数
- 数据结构实验之排序五:归并求逆序数
- 数据结构实验之排序五:归并求逆序数
- 数据结构实验之排序五:归并求逆序数