Problem Description
Recall the problem of finding the number of inversions. As in the course, we are given a sequence of n numbers a1,a2,⋯,an,and we define an inversion to be a pair i
We motivated the problem of counting inversions as a good measure of how different two orderings are. However, one might feel that this measure is too sensitive. Let’s call a pair a significant inversion if i<j and ai>3aj. Give an O(nlogn) algorithm to count the number of significant inversions between two orderings.
The array contains N elements (1<=N<=100,000). All elements are in the range from 1 to 1,000,000,000.
Input
The first line contains one integer N, indicating the size of the array. The second line contains N elements in the array.
- 50% test cases guarantee that N < 1000.
Output
Output a single integer which is the number of pairs of significant inversions.
Sample Input
1 | 6 |
Sample Output
1 | 6 |
主要思路
这一题是求解逆序数的变形题,仅仅是改变了ai>3aj这一条件,但是基本解题思路是一样的,使用了分治的策略,具体操作其实就是在归并排序的过程中记录一下“逆序数”的个数(这题的逆序数表示的是前面的数大于后面的数的三倍)。所以只需要写一个归并排序就能够解决这一问题,下面简单回顾一下归并排序。
归并操作
归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。(百度百科)
下面一个动态图,很直观的展示了归并的具体操作(来源https://www.jianshu.com/p/33cffa1ce613)
下面另举一个实例,这个例子来自百度百科(这里的逆序数表示的单纯的前面的数大于后面的数)
如设有数列{6,202,100,301,38,8,1}
初始状态分为若干部分:{6} {202} {100} {301} {38} {8} {1}
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
总的比较次数为:3+4+4=11;
逆序数为14;
代码(C++)
1 |
|