给出一列数a1,a2,a3....an,求它们的逆序对数,即有多少个有序对(i,j) 使得iaj,n高达10的6次方

时间:2023-03-10 01:49:22
给出一列数a1,a2,a3....an,求它们的逆序对数,即有多少个有序对(i,j) 使得iaj,n高达10的6次方

//归并排序

//#include<stdio.h>

//#include<string.h>

//#include<algorithm>

//#include<iostream>

//using namespace std;

//

//int n,m;

//int a[10],b[10];

//

//void merge_sort(int* A,int x,int y,int* T)

//{

//    if(y-x>1)

//    {

//        int m=(y-x)/2+x;

//        int p=x,q=m,i=x;

//        merge_sort(A,x,m,T);

//        merge_sort(A,m,y,T);

//        while(p<m||q<y)

//        {

//            if(q>=y||p<m&&A[p]<=A[q]) T[i++]=A[p++];//一石二鸟,控制左边和右边

//            else T[i++]=A[q++];

//        }

//        for(i=x; i<y; i++) A[i]=T[i];

//    }

//}

//

//int main()

//{

//    scanf("%d",&n);

//    while(n--)

//    {

//        int i,j;

//        memset(b,0,sizeof(b));

//        scanf("%d",&m);

//        for(i=0; i<m; i++)

//            scanf("%d",&a[i]);

//        merge_sort(a,0,m,b);

//        for(i=0; i<m; i++)

//            printf("%d ",a[i]);

//        printf("\n");

//    }

//    return 0;

//}









//给出一列数a1,a2,a3....an,求它们的逆序对数,即有多少个有序对(i,j)

//使得i<j,ai>aj,n高达10的6次方 

//思路:

//和归并排序一样,划分和递归求解都好办,关键在于合并;如何求出i在左边

//而j在右边的逆序对数呢?统计的常见技巧是"分类",我们按照j的不同把这些

//"跨越两边"的逆序对进行分类;只要对于右边的每个j,统计左边比它大的元素个数f(j)

//则所有f(j)的和就是答案

//幸运的是归并排序可以帮我们"顺便"完成f(j)的计算;由于合并操作是从小到大进行的

//当右边的A[j]复制到T中时,左边还没来得及辅助到T的那些数就是左边所有比A[j]大的数

//此时在累加器中加上左边元素个数m-p即可(左边所剩的元素在区间[p,m)中,因此个数是m-p)

//换句话说就是把"else T[i++]=A[q++]"改成"else{T[i++]=A[q++];cnt+=m-p;".注意cnt要清零

#include<stdio.h>

#include<string.h>

#include<algorithm>

#include<iostream>

using namespace std;





int n,m;

int cnt;

int a[10],b[10];





void merge_sort(int* A,int x,int y,int* T)

{

    cnt=0;

    if(y-x>1)

    {

        int m=(y-x)/2+x;

        int p=x,q=m,i=x;

        merge_sort(A,x,m,T);

        merge_sort(A,m,y,T);

        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-p;

            }

        }

        for(i=x; i<y; i++) A[i]=T[i];

    }

}





int main()

{

    scanf("%d",&n);

    while(n--)

    {

        int i;

        memset(b,0,sizeof(b));

        scanf("%d",&m);

        for(i=0; i<m; i++)

            scanf("%d",&a[i]);

        merge_sort(a,0,m,b);

        for(i=0; i<m; i++)

            printf("%d ",a[i]);

        printf("\n");

        printf("%d\n",cnt);

    }

    return 0;

}