归并排序求逆序对

来源:互联网 发布:sdk2000数据无效 编辑:程序博客网 时间:2024/05/20 11:47

1164: 分治 逆序对

时间限制: 1 Sec  内存限制: 128 MB

题目描述

给一列数a1,a2,...,an,求它的逆序对数,即有多少个有序对(i,j),使得i<j且ai>aj。n可以高达10^6。

输入

第一行输入整数N(2<=N<=10^6).
接下来一行N个正整数数分别是a1,a2,...,an(ai<=10^6)。

输出

输出一个数表示逆序对数。

样例输入

42 4 3 1

样例输出

4

重点体会分治思想!!

要熟练会写,有一道叫做手套的题就考了逆序对,一会贴上。
这里直接粘代码了
#include<iostream> #include<cstdio> using namespace std; int n,a[2000001],i,c[2000001]; long long ans; void x(int l,int r) {     int mid=(l+r)/2,i,j,tmp;     if(r>l)     {         x(l,mid);         x(mid+1,r);         tmp=l;         for(i=l,j=mid+1;i<=mid&&j<=r;)         {             if(a[i]>a[j])             {                 c[tmp++]=a[j++];                 ans+=mid-i+1;             }             else c[tmp++]=a[i++];         }         if(i<=mid) for(;i<=mid;) c[tmp++]=a[i++];         if(j<=r) for(;j<=r;) c[tmp++]=a[j++];         for(i=l;i<=r;i++) a[i]=c[i];     } } int main() {     cin>>n;     for(i=1;i<=n;i++) scanf("%d",&a[i]);     x(1,n);     cout<<ans; }
还有一份
#include<cstdio>  #include<iostream>  #include<algorithm>  using namespace std;  int A[9000010]={0},T[9000010]={0}; long long cnt=0;  void merge_sort(int x,int y)  {      if(y-x>=1){            int m=(y-x)/2+x;            int p=x,q=m+1,i=x;            merge_sort(x,m);             merge_sort(m+1,y);             while(p<=m||q<=y){                  if(q>y||(p<=m&&A[p]<=A[q]))T[i++]=A[p++];                  else {T[i++]=A[q++];cnt+=m+1-p;}             }             for(i=x;i<=y;i++)A[i]=T[i];      }          }  int main()  {         int n,m,ans=0,i,k;         scanf("%d",&n);         for(i=0;i<n;i++)         {             scanf("%d",&A[i]);                        }          merge_sort(0,n-1);          printf("%lld",cnt);             } 


0 0
原创粉丝点击