zoukankan      html  css  js  c++  java
  • 给出一列数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(" ");
    //    }
    //    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(" ");
            printf("%d ",cnt);
        }
        return 0;
    }


















  • 相关阅读:
    内容收缩伸展
    分页浏览的导航栏Bootstrap和js两种方法
    Bootstrap-缩略图
    Bootstrap-进度条
    Bootstrap-点击“&#215;”,可以关闭页面
    Bootstrap页头
    Bootstrap分页
    Bootstrap--面包屑路径导航
    Bootstrap--标签和徽章<新闻后面的new hot等>
    NSLog 去除上线版本
  • 原文地址:https://www.cnblogs.com/nyist-xsk/p/7264896.html
Copyright © 2011-2022 走看看