• 一本通1311 求逆序对(归并排序应用)


    【题目描述】

    给定一个序列a1,a2,,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目。

    【输入】

    第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。

    【输出】

    所有逆序对总数。

    【输入样例】

    4
    3
    2
    3
    2

    【输出样例】

    3


    逆序对实际上可以用冒泡排序来求,一个数交换了几次就说明有几个逆序,但是这样实在是太慢了,时间复杂度O(n*n)
    如果用归并,就可以排好序,然后找到第一组逆序,直接加上靠前的大数后面数的个数即可,比如:{3,4,7,9}和{1,5,8,10}
    发现3要比1大,那么3后面的数自然都比1大,再加上3本身,所以就有mid-i+1个逆序了


    代码:


    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    long long a[1000001],r[1000001];//根据取值范围定义数组(多打几个零不要在意,只要注意不要爆空间就行)
    long long ans; //这里都用long long
    void msort(long long s,long long t)
    {
    if(s == t) return;//如果只有一个数,自然不用排序,直接返回
    long long mid = (s + t) / 2;
    msort(s,mid);//虽然还没有开始写排序代码,但是可以直接进行递归(我也不太明白,要请教大佬)

    msort(mid + 1,t);//归并排序名字由此得来,分开排序再合在一起
    long long i = s,j = mid + 1,k = s;
    while(i <= mid&&j <= t)//当满足前面的数在序列前半部分已经后面的数在序列后半部分时
    {
    if(a[i] <= a[j])//如果没有逆序,那么新数组存放较小的数(从小到大排序)
    r[k ++] = a[i ++];
    else
    {
    ans += mid - i + 1;//如果出现逆序,那么参考思路,直接套公式
    r[k ++] = a[j ++];//还是把较小的数放进去
    }
    }
    while(i <= mid)//如果有一边没有放完,那么放进去
    r[k ++] = a[i ++];
    while (j <= t)
    r[k ++] = a[j ++];
    for(long long i = s;i <= t;i ++)
    a[i] = r[i];//将新数组里的数据再存回到原先的数组里去
    }
    int main()
    {
    long long n;
    cin >> n;
    for(long long i = 1;i <= n;i ++)
    cin >> a[i];
    msort(1,n);
    cout << ans;
    return 0;
    }

  • 相关阅读:
    Apache Ant 1.9.1 版发布
    Apache Subversion 1.8.0rc2 发布
    GNU Gatekeeper 3.3 发布,网关守护管理
    Jekyll 1.0 发布,Ruby 的静态网站生成器
    R语言 3.0.1 源码已经提交到 Github
    SymmetricDS 3.4.0 发布,数据同步和复制
    beego 0.6.0 版本发布,Go 应用框架
    Doxygen 1.8.4 发布,文档生成工具
    SunshineCRM 20130518发布,附带更新说明
    Semplice Linux 4 发布,轻量级发行版
  • 原文地址:https://www.cnblogs.com/57xmz/p/12595767.html
Copyright © 2020-2023  润新知