zoukankan      html  css  js  c++  java
  • NYOJ117 求逆序数

    求逆序数

    时间限制:2000 ms  |  内存限制:65535 KB
    难度:5
     
    描述

    在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

    现在,给你一个N个元素的序列,请你判断出它的逆序数是多少。

    比如 1 3 2 的逆序数就是1。

     
    输入
    第一行输入一个整数T表示测试数据的组数(1<=T<=5)
    每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000)
    随后的一行共有N个整数Ai(0<=Ai<1000000000),表示数列中的所有元素。

    数据保证在多组测试数据中,多于10万个数的测试数据最多只有一组。
    输出
    输出该数列的逆序数
    样例输入
    2
    2
    1 1
    3
    1 3 2
    样例输出
    0
    1

    算法解析:
      n这么大,O(n2)的枚举将超时,因此需要更高效的算法。受到归并排序的
    启发,我们来试试"分治三步法"是否适用。"划分问题"过程就是把序列分成元素
    个数尽量相等的两半;"递归求解"是统计i和j均在左边或者均在右边的逆序数对
    的个数;"合并问题"则是统计i在左边,但j在右边的逆序数对个数。
    由于归并排序中的合并操作时从小到大进行的,当右边的A[j]复制到T中时,
    左边还没来的及复制到T的那些数就是左边所有比A[j]大的数。此时在累加器中
    加上左边元素个数 mid - s1 即可(左边元素在区间[s1, mid) 中,
    因此元素个数为mid - s1)。
      参考资料--刘汝佳《算法竞赛入门经典》 第144页

     1 #include <cstdio>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 const int N = 1000005;
     7 int a[N], tmp[N];
     8 long long cnt;   //  注意这里必须用 long long,因为数据量很大
     9 
    10 void merge_sort(int *A, int start, int end, int *T)// 左闭右开区间
    11 {
    12     if(end - start > 1)
    13     {
    14         int mid = start + ((end - start) >> 1);//  划分
    15         int s1 = start, s2 = mid, i = start;
    16         merge_sort(A, start, mid, T);
    17         merge_sort(A, mid, end, T);
    18         while(s1 < mid || s2 < end)
    19         {
    20             if(s2 >= end || (s1 < mid && A[s1] <= A[s2]))
    21                 T[i++] = A[s1++];
    22             else
    23             {
    24                 T[i++] = A[s2++];
    25                 cnt += mid - s1;
    26             }
    27         }
    28         for(int i = start; i < end; ++i)
    29             A[i] = T[i];
    30     }
    31 }
    32 
    33 int main()
    34 {
    35     int T, n;
    36     scanf("%d", &T);
    37     while(T--)
    38     {
    39         cnt = 0;
    40         scanf("%d", &n);
    41         for(int i = 0; i < n; ++i)
    42             scanf("%d", &a[i]);
    43         merge_sort(a, 0, n, tmp);
    44         printf("%lld\n", cnt);
    45     }
    46     return 0;
    47 }


    功不成,身已退
  • 相关阅读:
    nginx能访问html静态文件但无法访问php文件
    LeetCode "498. Diagonal Traverse"
    LeetCode "Teemo Attacking"
    LeetCode "501. Find Mode in Binary Search Tree"
    LeetCode "483. Smallest Good Base" !!
    LeetCode "467. Unique Substrings in Wraparound String" !!
    LeetCode "437. Path Sum III"
    LeetCode "454. 4Sum II"
    LeetCode "445. Add Two Numbers II"
    LeetCode "486. Predict the Winner" !!
  • 原文地址:https://www.cnblogs.com/dongsheng/p/2947069.html
Copyright © 2011-2022 走看看