zoukankan      html  css  js  c++  java
  • AcWing 超快速排序

    每发现相邻数字顺序颠倒即将其交换,此时序列的逆序数减一.所以求出给定序列逆序和即可.

    求逆序和最简单的方法是冒泡排序,但是O(n2)是很不好的算法.

    常用的求逆序和方法有归并排序和树状数组,这里使用归并排序方法.实现见此模板.(假设数组下标从1开始)

    void merge(int l, int r){
        if(l == r) return;
        int mid = l + r >> 1;
        merge(l, mid);
        merge(mid + 1, r);
        int i = l, j = mid + 1;
        for(int k = l; k <= r; k++)
            if(j > r || i <= mid && s[i] < s[j]) tmp[k] = s[i++];    // 注意如果序列中有重复数字需要改为s[i] <= s[j]
            else tmp[k] = s[j++], ct += mid - i + 1;
        for(int k = l; k <= r; k++) s[k] = tmp[k];
    }

    执行该函数后,数组s将被按升序排列,且ct(假设初始化为0)的值即为原序列的逆序数.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    long long s[500010], b[500010], n, ct;
    
    void merge(int l, int r){
        if(r <= l) return;
        int mid = l + r >> 1;
        merge(l, mid);
        merge(mid + 1, r);
        int i = l, j = mid + 1;
        for(int k = l; k <= r; k++)
            if(j > r || i <= mid && s[i] < s[j]) b[k] = s[i++];
            else b[k] = s[j++], ct += mid - i + 1;
        for(int i = l; i <= r; i++) s[i] = b[i];
    }
    
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0),cout.tie(0);
        while(cin >> n){
            if(!n) break;
            ct = 0;
            for(int i = 1; i <= n; i++) cin >> s[i];
            merge(1, n);
            cout << ct << endl;
        }
    
        return 0;
    }
    AC Code
  • 相关阅读:
    异常问题处理记录(转载篇)
    linux服务器出现大量连接:sshd: root@notty
    第4章 Python运算符
    第2章 python基础知识
    第1章 python环境搭建
    Tomcat漏洞升级
    第3章 数据类型、运算符和表达式
    第2章 C语言基础知识
    第1章 概述
    第1章 企业管理概论
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14167585.html
Copyright © 2011-2022 走看看