zoukankan      html  css  js  c++  java
  • 一本通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;
    }

  • 相关阅读:
    kuangbin_ShortPath K (POJ 3159)
    kuangbin_ShortPath I (POJ 2240)
    kuangbin_ShortPath H (POJ 3660)
    kuangbin_ShortPath G (POJ 1502)
    kuangbin_ShortPath J (POJ 1511)
    kuangbin_ShortPath F (POJ 3259)
    kuangbin_ShortPath E (POJ 1860)
    StoryBoard中使用xib
    iOS APP 架构漫谈[转]
    Mac 快速修改 hosts 文件
  • 原文地址:https://www.cnblogs.com/57xmz/p/12595767.html
Copyright © 2011-2022 走看看