zoukankan      html  css  js  c++  java
  • 【上海交大oj】逆序数对(归并排序)

    Description

    给你一个数组,求该数组的逆序数

    Input Format

    输入文件第一行包含一个自然数N,N个数 接下来有N行,表示a[0],a[1]...a[n - 1]

    Output Format

    输出文件仅有一行包含一个整数,表示该数组的逆序数

    Sample Input

    3
    575085724
    344369358
    808884464
    

    Sample Output

    1
    ==============================================
    所谓逆序数,就是一个数列中的元素,比它大并且排在它前面的数的个数,然后对每个元素逆序数求和就是答案。
    如果直接做的话,对每个数都要扫描它前面的所有数,复杂度为n^2,因此可以用归并排序的思想。所谓归并排序,有点类似分治法,比如4,1,3,2,首先把序列分为两半并调用归并函数(递归直到只有一个元素)分别得到两个有序子序列,然后对这两个子序列进行归并.归并过程是这样的:
    对两个子序列同时从左到右扫描,选取较小值加入序列。对于1,42,3,选取顺序是为:1->2->3->4.
    那么怎么统计逆序数对呢?举个例子,当扫描到3时,对于它自身所在子序列:在它以前的元素肯定比它小,不计,在它后面的元素在因为在对这个子序列排序时已经计算过了(原来是3,2,子序列分别为3和2,那么扫描到2的时候会对3统计)也不用计。对于这个时刻和它进行比较的子序列:此时和它比较的元素以前的肯定比它小(如1,4中的元素4以前的元素(1)),不计,只要计算和它比较的元素本身及之后的元素就行了。
    因此,等到排完序(nlogn)后,逆序数对也就求出来了。
    具体代码:
     1 #include <iostream>
     2 using namespace std;
     3 long long n,count = 0;
     4 long long arr[100000],a[100000],b[100000];//要计算的序列和两个子序列 
     5 void mergesort(int , int);
     6 void merge(int, int, int);//归并过程 
     7 int main(){
     8     int n;
     9     
    10     cin>>n;
    11     for (int i = 0; i < n;++i) cin>>arr[i];
    12     mergesort(0,n-1);
    13     cout<<count;
    14     
    15     return 0;
    16 }
    17 void merge(int l,int m,int r){
    18     if (l==r) return;
    19     int len1 = m - l + 1,p = 0,q = 0;
    20     int len2 = r - m;
    21     for (int i = 0;i < len1;++i) a[i] = arr[i+l];
    22     for (int i = 0;i < len2;++i) b[i] = arr[m+i+1];
    23     a[len1] = 1000000000000000000;
    24     b[len2] = 1000000000000000000;
    25     for (int i = l;i <= r;++i){
    26         if (a[p] <= b[q]) arr[i] = a[p++];
    27         else{
    28             count += m - p -l + 1;//计算逆序数对 
    29             arr[i] = b[q++];
    30         } 
    31     }
    32 }
    33 void mergesort(int l,int r){
    34     if (l>=r) return;
    35     int m = (l+r)/2;
    36     mergesort(l,m);
    37     mergesort(m+1,r);
    38     merge(l,m,r);
    39 }
    View Code


  • 相关阅读:
    36、基于TCP、UDP协议的嵌套字通信
    34、异常以及网络编程
    作业4月15号
    31、反射与内置方法、元类
    30、多态与鸭子类型以及内置函数
    作业4月9号
    29、继承
    作业4月8号
    28、封装
    27、面向对象
  • 原文地址:https://www.cnblogs.com/wenma/p/4550624.html
Copyright © 2011-2022 走看看