zoukankan      html  css  js  c++  java
  • 归并排序 霍纳规则(法则) 统计逆序对

    归并排序

    又称合并排序,其核心是分治思想。分治法详细请看百度百科

    《算导》p20:分治法中的递归式是基于基本模式中的三个步骤的。如先前一样,设T(n)为一个规模为n的问题的运行时间。如果问题的规模足够地小,如n≤c(c为一个常量),则得到它的直接解的时间为常量,写作Θ(1)。假设我们把原问题分解成a个子问题,每一个的大小是原问题的1/b。(对于合并排序,a和b都是2,但在许多分治法中,a≠b。)如果分解该问题和合并解的时间各为D(n)和C(n),则得到递归式:

    我们则知道,归并时间复杂度是Θ(n lg n)的了(具体看算导p20-p22)

    上我自己的代码

    #define WHI(i,a,n) for(i=(a);i<(n);++i)
    #define REP(i,a,n) for(int i=(a);i<(n);++i)
    
    const int MAXi = 1e5+10, oo = ~0u>>1;
    int L[MAXi], R[MAXi];
    
    void merge_sort(int* arr, int f, int l){
    	if(f < l-1){
    		int m = (f+l) >> 1, i = 0, j = 0;
    		merge_sort(arr, f, m);
    		merge_sort(arr, m, l);
    		WHI(i, 0, m-f) L[i] = arr[f+i];
    		WHI(j, 0, l-m) R[j] = arr[m+j];
    		L[i] = R[j] = oo; i = j = 0;
    		while(f < l)
    			arr[f++] = L[i] < R[j] ? L[i++] : R[j++];
    	}
    }

     

    霍纳规则(法则)

    即“秦九韶方法” 用来计算多项式我们用D(i)来表示可推出

    顺推:   答案是D(n)

    逆推: 答案是D(0)

    很容易看出可以用滚动求值,即D = a(n-1) + x * D 或 D = a(i) + x * D

    代码

    //顺推
    for(int i = 0, D = 0; i <= n; ++i)
    	D = a[n-i] + x * D;
    //逆推
    for(int i = n, D = 0; i >= 0; ++i)
    	D = a[i] + x * D;

    统计逆序对

    含义:对于一个包含N个非负整数的数组A[1..n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个。

    很快就能用插入排序来统计,但O(n^2)咱们不采用,咱们用O(n lg n)的归并啦 >_<

    代码

    #define WHI(i,a,n) for(i=(a);i<(n);++i)
    #define REP(i,a,n) for(int i=(a);i<(n);++i)
    
    const int MAXi = 1e5+10, oo = (~0u>>1)+1;
    
    typedef unsigned long long ull;
    
    ull cnt;
    int L[MAXi], R[MAXi];
    
    void mi_cnt(int* arr, int f, int l){
    	if(f < l-1){
    		int m = (f+l) >> 1, i = 0, j = 0;
    		mi_cnt(arr, f, m);
    		mi_cnt(arr, m, l);
    		WHI(i, 0, m-f) L[i] = arr[f+i];
    		WHI(j, 0, l-m) R[j] = arr[m+j];
    		L[i] = R[j] = oo; i = j = 0;
    		while(f < l)
    			if(L[i] > R[j]){
    				arr[f++] = L[i++];
    				cnt += l-m-j;
    			}
    			else
    				arr[f++] = R[j++];
    	}
    }

    OK。写完文章了,欢迎大家指点~

  • 相关阅读:
    C++逐行读取文本文件的正确做法
    <Android Framework 之路>Android5.1 Camera Framework(一)
    zeromq-4.1.2在windows下的编译
    Duilib应用修改程序图标方法
    gdal集成kml库的做法
    使用DWR实现JS调用服务端Java代码
    DirectUI界面编程(六)实现右键弹出菜单
    如何设计系统的错误码及错误信息
    TCP协议格式
    UDP协议
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3523120.html
Copyright © 2011-2022 走看看