逆序对的数量

题目描述

给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。

逆序对的定义如下:对于数列的第  个和第  j  个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。

【输入格式】

第一行包含整数 n,表示数列的长度。

第二行包含 n 个整数,表示整个数列。

【输出格式】

输出一个整数,表示逆序对的个数。

【数据范围】

1n100000
数列中的元素的取值范围 [1,109]

【输入样例】

6

2 3 4 5 6 1

【输出样例】

5

分治策略一般分为拆分,求解,合并三个过程;本题利用归并排序过程中的合并过程。

 

 

 由于归并排序合并过程中,两个待合并数组已然有序,因此可以利用这种“有序”来计算逆序对的数量。

当前半部分走到i,后半部分走到j时,假设num[i] > num[j],那么就意味着从i到mid的位置的所有数num[i~mid]都大于num[j],构成了一对逆序对,因此通过计算从i到mid共有mid - i + 1个数,即可知道当前状态下的逆序对

 

 1 #include <iostream>
 2 using namespace std;
 3 const int N = 100009;
 4 int num[N],tmp[N],n;
 5 long long res;
 6 
 7 long long mergeSort(int l,int r)
 8 {
 9     if(l >= r)
10         return 0;
11     int mid = l + r >> 1;
12     res = mergeSort(l,mid) + mergeSort(mid + 1,r);
13     
14     int i = l,j = mid + 1, k = 0;
15     while(i <= mid && j <= r)
16     {
17         if(num[i] <= num[j])
18             tmp[k++] = num[i++];
19         else
20         {
21             tmp[k++] = num[j++];
22             res += mid - i + 1;
23         }
24     }
25     while(i <= mid)
26         tmp[k++] = num[i++];
27     while(j <= r)
28         tmp[k++] = num[j++];
29     for(int i = l,j = 0;i <= r;++i,++j)
30         num[i] = tmp[j];
31     return res;
32 }
33 
34 int main()
35 {
36     cin >> n;
37     for(int i = 0;i < n;++i)
38         cin >> num[i];
39     cout << mergeSort(0,n-1) << endl;
40     return 0;
41 }

 

posted @ 2021-10-16 00:06  Modest-Hamilton  阅读(226)  评论(0)    收藏  举报