Yibentong 1311: [Example 2.5] Find reverse pair, merge sort

This question is not difficult, a template question. The reason why I write this solution is because when I first submitted it, there was no AC. Lao Tzu was immediately dumbfounded. After patiently analyzing the data, I discovered where my mistakes were. Through the drama, it fell into the pit of data out of bounds. So record it.

Title
Title Link
A pass OJ: http://ybt.ssoier.cn:8088/problem_show.php?pid=1311.

OJ:http://47.110.135.197/problem.php?id=4134。

 

Analyze
a standard question in reverse order.

Reverse order pair
Let A be an ordered set with n numbers (n> 1), where all numbers are different. If there is a positive integer i, j such that 1 ≤ i <j ≤ n and A [i]> A [j], then the ordered pair <A [i], A [j]> is called an inverse pair of A, and Called the reverse order number.

For example, the reverse pairs of the array (3, 1, 4, 5, 2) are (3, 1), (3, 2), (4, 2), (5, 2), a total of 4 reverse pairs.

Algorithm idea To
find the reverse order of an array is to sort the array, and record the number of reverse orders in the sorting process. In this way, we need to use stable sorting algorithms, such as bubble sort, insert sort and merge sort.

Data range analysis
1. From the title, we can know that the range of n is [1, 10 ^ 5], so that we know that all sorting algorithms of O (n ^ 2) complexity must be TLE, which means bubble sorting And insertion sort can not be used, only to merge sort.

2. Assuming the worst case, that is, the 10 ^ 5 data are all in reverse order, then the reverse order should be.

What does this data mean? Let's recall that the maximum range of the C ++ data type unsigned int is 4,294,967,295, that is to say, unsigned int can not accommodate this data. My wife is fooling.

Merging and sorting to find reverse order pairs
This part is the core of the analysis. First, we use a sample data to illustrate, using merge sort. Suppose we have a sequence of numbers [5 4 2 6 3 1], and use merge sort to see how many reverse pairs.

The first step: two points, as shown below. Reverse order number = 0.

The second step: the fourth layer 5 and 4 merge: i = l = 1; r = 2; mid = (l + r) / 2 = 1; j = mid + 1 = 2; because 5> 4, the number of pairs in reverse order + mid-i + 1 = 1. b array: [4 5 0 0 0 0], j + 1> r; exit; a array [4 5 2 6 3 1]. As shown below.

The third step: the fourth layer 6 and 3 merge: i = l = 4; r = 5; mid = (l + r) / 2 = 4; j = mid + 1 = 5; because 6> 3, the number of reverse order pairs + mid-i + 1 = 2. b array: [4 5 0 3 6 0], j + 1> r; exit; a array [4 5 2 6 3 1]. As shown below.

The fourth step: the third layer 4,5 and 2 are merged: i = l = 1; r = 3; mid = (l + r) / 2 = 2; j = mid + 1 = 3; because 4> 2, the reverse order For quantity + mid-i + 1 = 4. b array: [2 4 5 3 6 0], j + 1> r; exit; a array [2 4 5 3 6 1]. As shown below.

The fifth step: the third layer 3,6 and 1 merge: i = l = 4; r = 6; mid = (l + r) / 2 = 5; j = mid + 1 = 6; because 3> 1, reverse order For quantity + mid-i + 1 = 6. b array: [2 4 5 1 3 6], j + 1> r; exit; a array [2 4 5 1 3 6]. As shown below.

Step 6: The second layer 2,4,5 and 1,3,6 merge: i = l = 1; r = 6; mid = (l + r) / 2 = 3; j = mid + 1 = 4; Because 2> 1, the reverse order is + mid-i + 1 = 9. b array: [1 2 4 5 3 6], j + 1; corresponding to 2 <3, b array: [1 2 4 5 3 6], i + 1; corresponding to 4> 3, reverse order number + mid-i + 1 = 11, b array: [1 2 3 4 5 6]. j + 1; corresponding to 4 <6, b array: [1 2 3 4 5 6]; i + 1, 5 <6, b array: [1 2 3 4 5 6]; i + 1> mid, exit, a Array [1 2 3 4 5 6], ordered. As shown below.

From the above analysis, we can see that the most important thing is to use the merge sort to find the reverse sequence pair.

ans+=mid-i+1;

//http://ybt.ssoier.cn:8088/problem_show.php?pid=1311
//求逆序对
#include <bits/stdc++.h>
using namespace std;
 
const int MAXN = 1e6+4;
int nums[MAXN] = {};
int tmps[MAXN];
long long ans = 0;
 
//使用归并排序
void merge(int l, int mid, int r) {
    int i=l;
    int j=mid+1;
    int k=l;
    while (i<=mid && j<=r) {
        if (nums[i]>nums[j]) {
            tmps[k++]=nums[j++];
            ans+=mid-i+1;
        } else {
            tmps[k++]=nums[i++];
        }
    }
 
    while (i<=mid) {
        tmps[k++]=nums[i++];
    }
    while (j<=r) {
        tmps[k++]=nums[j++];
    }
    for (i=l; i<=r; i++) {
        nums[i]=tmps[i];
    }
}
 
void mergeSort(int l, int r) {
    int mid;
    if (l < r) {
        mid = l+((r-l)>>1);
        mergeSort(l, mid);
        mergeSort(mid+1, r);
        merge(l, mid, r);
    }
}
 
int main() {
    int n;
    cin >> n;
    int i;
    for (i=0; i<n; i++) {
        cin >> nums[i];
    }
 
    mergeSort(0, n-1);
 
    cout << ans << endl;
 
    return 0;
}


————————————————
Copyright Statement: This article is an original article of CSDN blogger "The Old Week of Efforts", following the CC 4.0 BY-SA copyright agreement, please attach the original source link for reprint And this statement.
Original link: https://blog.csdn.net/justidle/article/details/104565227

 

Posted 33 original articles · liked 0 · visits 167

Guess you like

Origin blog.csdn.net/weixin_42790071/article/details/105436355