zoukankan      html  css  js  c++  java
  • AcWing 788.逆序对的数量

    AcWing 788.逆序对的数量

    原题链接

    思路

    • 暴力的思路
      暴力是最容易想到的思路,但是时间复杂度有点高,当数组中数比较多的时候一般会超时
    代码如下:
    ll res = 0;
        for(int i = 0; i < n; ++ i){
            for(int j = i + 1; j < n; ++ j){
                if(q[i] > q[j]) res ++;
            }
        }
    
    • 归并排序的方式
      这个题目是归并排序的一个拓展应用,逆序对是下标小而数值大的一对数,我们知道在归并排序的过程中,每次分为两组进行比较,前面一组的下标比后面一组下标要小,如果在比较的过程中发现了逆序对,因为每一组中都是有序的,那么其后面的数都可以与后面分组中的那个数构成逆序对,这样就可以快速的求出逆序对的数量。

    这样做时间复杂度降为了O(NlogN)

    代码如下
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int N = 100010;
    int n, tmp[N];
    
    ll mager_sort(int q[], int l, int r){
        if(l >= r) return 0;
        int mid = l + r >> 1;
        //总的逆序对的数量等于左边分组、右边分组和左右两边之和(其中左边和右边由递归返回求出)
        ll res = mager_sort(q, l, mid) + mager_sort(q, mid + 1, r);
        int i = l, j = mid + 1, k = 0;
        while(i <= mid && j <= r){
            if(q[i] <= q[j]) tmp[k ++] = q[i ++];
            else {
                res += mid - i + 1;//如果此时q[i] > q[j]那么i所在的分组中后续所有的数都比q[j]大
                tmp[k ++] = q[j ++];
            }
        }
    
        while(i <= mid) tmp[k ++] = q[i ++];
        while(j <= r) tmp[k ++] = q[j ++];
        for(i = l, j = 0; i <= r; ++ i, ++ j) q[i] = tmp[j];
    
        return res;
    }
    
    int main(){
        ios::sync_with_stdio(false);
        int q[N]; cin >> n;
        for(int i = 0; i < n; ++ i) cin >> q[i];
    
        cout << mager_sort(q, 0, n - 1) << endl;
    
        return 0;
    }
    
  • 相关阅读:
    弱引用的字典WeakDictionary(转)
    XBox360调试程序失败:Unable to start debugging.Connection to Xbox360 development kit lost
    托管C++中的范型和模板的区别
    智能指针的缺陷
    托管C++笔记(二)原创
    C#通过WMI操作本地共享文件夹
    很随便的随笔
    "The system cannot execute the specified program"
    C++多重继承
    托管C++笔记(一)原创
  • 原文地址:https://www.cnblogs.com/Lngstart/p/14261024.html
Copyright © 2011-2022 走看看