poj 2299 逆序数 归并排序
2012-04-14 00:54
267 查看
陷阱啊!一开始我用冒泡排序(Bubble Sort)来统计。。晕,TLE。each case 50w.而一趟冒泡排序需要进行的是n-1,n-2,……,2,1,0的和次比较。即n*(n-1)/2次。总的时间复杂度为O(n^2).肯定是吃不消的。
于是,可以用归并排序来求它的逆序数,逆序即为它总共需要变换的次数。这样时间复杂度是nlog2n,而空间复杂度2n。 利用归并求逆序关键是对子序列s1和s2在归并时(s1,s2已经排好序),若s1[i]>s2[j](逆序状况),则逆序数加上s1.length-i,因为s1中i后面的数字对于s2[j]都是逆序的。参考:http://www.slyar.com/blog/poj-2299-c.html
于是,可以用归并排序来求它的逆序数,逆序即为它总共需要变换的次数。这样时间复杂度是nlog2n,而空间复杂度2n。 利用归并求逆序关键是对子序列s1和s2在归并时(s1,s2已经排好序),若s1[i]>s2[j](逆序状况),则逆序数加上s1.length-i,因为s1中i后面的数字对于s2[j]都是逆序的。参考:http://www.slyar.com/blog/poj-2299-c.html
#include <iostream> #include <fstream> using namespace std; #define MAX 500005 int a[MAX],t[MAX]; __int64 cnt; void Merge(int l,int mid,int r) { int i=l,j=mid+1,k=0; while(i<=mid && j<=r) { if(a[i]>a[j]) { t[k++]=a[j++]; cnt+=mid-i+1; } else { t[k++]=a[i++]; } } while(i<=mid) t[k++]=a[i++]; while(j<=r) t[k++]=a[j++]; //将归并完成的结果复制到原数组中 for(i=0; i<k; i++) { a[l+i]=t[i]; } } void MergeSort(int l,int r) { int mid=(l+r)/2; if(l<r) { MergeSort(l,mid); MergeSort(mid+1,r); Merge(l,mid,r); } } int main(){ int n,i; freopen("acm.txt","r",stdin); while( scanf("%d",&n)!=EOF && n) { for(i=0; i<n; i++) { scanf("%d",&a[i]); } cnt=0; MergeSort(0,n-1); printf("%I64d\n",cnt); } return 0; }
相关文章推荐
- POJ 2299 Ultra-QuickSort 求逆序对数(归并排序,树状数组)
- POJ 2299 归并排序求逆序数
- poj 2299/归并排序、逆序数
- (应用排序算法编程7.2.2)POJ 2299 Ultra-QuickSort(使用归并排序来计算逆序对的个数)
- poj 2299 Ultra-QuickSort 归并排序求解逆序对
- poj 2299 Ultra-QuickSort——归并排序求逆序数,线段树离散化
- POJ2299——归并排序求逆序对数
- poj 2299 归并排序求逆序对 解题报告
- POJ2299(归并排序求逆序对)
- poj 2299 求逆序对 树状数组 归并排序
- poj 2299 归并排序求逆序数
- poj 2299 Ultra-QuickSort(归并排序求逆序对)
- POJ2299 归并排序求逆序数
- poj-2299 Ultra-QuickSort 归并排序求逆序数
- Ultra-QuickSort (poj 2299 归并排序 || 树状数组 求逆序对)
- POJ 2299 分治法求数列逆序对(归并排序)
- poj 2299 利用归并排序求逆序数
- POJ_2299_Ultra-quicksort_归并排序、逆序数
- POJ 2299 Ultra-QuickSort(归并排序求逆序对数)
- poj 2299 树状数组+离散化 or 归并排序 求逆序对