POJ 2299 - Ultra-QuickSort 统计逆序对

来源:互联网 发布:理发软件下载 编辑:程序博客网 时间:2024/04/29 10:51

  可以交换相邻的数,问最少交换几次后数列变成非降的..

  对于每个数若小于左边的数与左边的数交换..大于右边的数与右边的数交换...如此可以推出所求的答案等价为这个数列的逆序数...

  如果暴力查找逆序数是O(n^2)的...对于此题数据.不可接受...

  采用分治的思想...在归并排序的过程中边排序边统计逆序数的个数...


Program:

#include<iostream>#include<stdio.h>#include<string.h>#include<set>#include<ctime>#include<algorithm>#include<queue>#include<cmath>#include<map>#define oo 100000007#define ll long long#define pi acos(-1.0)#define MAXN 500005using namespace std; int n,a[MAXN],temp[MAXN];ll ans; void merge(int s1,int e1,int s2,int e2){      int x,i,j,num=0;      i=s1,j=s2;      for (x=s1;x<=e2;x++)      {             if (i>e1) temp[x]=a[j++];                else             if (j>e2) temp[x]=a[i++];               else             if (a[i]>a[j])             {                   temp[x]=a[j++];                   ans+=e1-s1+1-num; //从后面段插进来的数插在了多少个前面段数的前面...             }else temp[x]=a[i++],num++;      }      for (i=s1;i<=e2;i++) a[i]=temp[i];      return;}void merge_sort(int l,int r){      if (l==r) return;      int mid=(l+r)/2;      merge_sort(l,mid);      merge_sort(mid+1,r);      merge(l,mid,mid+1,r);      return;}int main(){       int i;      while (~scanf("%d",&n))      {               if (!n) break;               for (i=1;i<=n;i++) scanf("%d",&a[i]);               ans=0;               merge_sort(1,n);               printf("%I64d\n",ans);      }      return 0;}


原创粉丝点击