前言
求逆序对的数目的题目一般不会直接给出,而是给出一个情景,然后让你来判断,接下来我将为大家讲解逆序对相关的内容
一、逆序对是什么?
上网搜了一下:
设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。
如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。
通俗的数就是数组下标大的反而小,求满足这种条件地数目
二、如何求逆序对
1.暴力
暴力无非就是两层for循环嵌套,但是遇到求逆序对地题目,基本不会让你用暴力来求解,因为一用暴力就会超时,一般就用归并排序即可。(这里就不多介绍了,我相信大家都会)
2.归并排序(求逆序对)
归并排序模板
void merge_sort(int q[],int l,int r)//归并排序模板
{
if(l >= r)return ;
int mid=(l + r)>>1;
merge_sort(q , l , mid);
merge_sort(q , mid+1 , r);
int i = l,j = mid+1,k = 0;
while(i <= mid && j <= r){
if(q[i]<=q[j])tmp[k++] = q[i++];//把小的存进去 k++先使用在加加
else{
tmp[k++] = q[j++];
}
}
//扫个尾
while(i <= mid) tmp[k++] = q[i++];
while(j <= r) tmp[k++] = q[j++];
for(int i = l,j = 0;i <= r;i ++,j ++){
q[i] = tmp[j];//还给原数组
}
return ;
}
求逆序对只需要对归并排序模板稍作改变即可
AC代码:
//归并排序
//模板
#include<iostream>
using namespace std;
using ll=long long;
int q[100010],tmp[100010];
ll res;
ll merge_sort(int q[],int l,int r)//归并排序模板
{
if(l >= r)return 0;
int mid=(l + r)>>1;
res = merge_sort(q , l , mid)+merge_sort(q , mid+1 , r);
int i = l,j = mid+1,k = 0;
while(i <= mid && j <= r){
if(q[i]<=q[j])tmp[k++] = q[i++];//把小的存进去 k++先使用在加加
else{
res+=mid-i+1;
tmp[k++] = q[j++];
}
}
//扫个尾
while(i <= mid) tmp[k++] = q[i++];
while(j <= r) tmp[k++] = q[j++];
for(int i = l,j = 0;i <= r;i ++,j ++){
q[i] = tmp[j];//还给原数组
}
return res;
}
int main()
{
int n;
cin>>n;
for(int i = 0;i < n;i ++)
cin>>q[i];
cout<<merge_sort(q,0,n-1)<<endl;
return 0;
}