题目链接:https://www.luogu.com.cn/problem/P1908
题意:
——求出所给序列中所有可能的逆序对
样例说明:
下标 i | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
数值 k | 5 | 4 | 2 | 6 | 3 | 1 |
5的下标—>0, 4的下标—>1 ,
5 > 4,但是下标 0 < 1
所以5 - 4可以构成一个逆序对,按照这种规则找出样例中所有的逆序对为 11 对
解法一: 爆破
双层for循环寻找所有逆序对,只能得一点分,在题目所给数据范围中会超时
代码:
int ans = 0;
for(int i = 0; i < n - 1; i++)
{
for(int j = i + 1; j < n; j++)
{
if(arr[i] > arr[j])
ans++;
}
}
解法二: 归并排序
—— 二路归并排序的算法思想,恰好可以利用到这题中
—— [ part1 ] [ part2 ] 通过两两比较合并,构成一个新的[ part3 ], 这是思路前提,先说明白放在这
—— 归并算法是可以利用递归实现的,所以,假设,我们的递归返回到第二层,此时的part1 和part2 都是有序的,如图
—— 按照归并的合并思路,此时的part1 和part 2是要一一比较的,
—— 设 i 走到 3 ,j 走到 2,那么 按照逆序对的规定 3 - 2是可以构成一个逆序对的,由于part1中3及其后面的元素值都是>=3的,因此,要计算part1中3后面有几个元素,这几个元素都是可以跟part2 中的2构成一个逆序对的。然后,part2中的元素2 就完成使命了。
ans += (R1 - i + 1);
—— 层层按照这种规则,可以使复杂度降低
完整代码:
#include <bits/stdc++.h>
using namespace std;
long long int ans;
vector<int > arr;
void Merge(int L1, int R1, int L2, int R2)
{
int i = L1, j = L2;
vector<<