给定一个长度为n的整数数列,请你计算数列中的逆序对的数量。
逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i < j 且 a[i] > a[j],则其为一个逆序对;否则不是。
Input:
第一行包含整数n,表示数列的长度;第二行包含 n 个整数,表示整个数列。(1≤n≤100000)
Output:
输出一个整数,表示逆序对的个数。
Input:
6
2 3 4 5 6 1
Output:
5
Solution:
归并排序思想求逆序对,B站详解归并排序~ B站是个宝藏...
Picture:
ps来源上面B站视频里的图片,描述了一下递归搜索的过程...
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[100010],b[100010];///b[]临时数组
ll ans;///记录逆序对数 数据大 易超int
void merge(int l,int m,int r)
{
//cout<<l<<" "<<r<<endl;
int i=l;///左半区域第一个节点地址
int j=m+1;///右半区域第一个节点地址
int pos=l;///临时数组的下标位置
while(i<=m&&j<=r)///在范围内
{
if(a[i]<=a[j]) ///排序进入临时数组
{
b[pos++]=a[i++];
}
else
{
b[pos++]=a[j++];
ans+=m-i+1;//i~m 排序好的数 和j 都能构成逆序对
}
}
while(i<=m)///左半区域还有剩余元素
b[pos++]=a[i++];
while(j<=r)///右半区域还有剩余元素
b[pos++]=a[j++];
for(int i=l;i<=r;i++)///排序后 更新a[]数组l~r
a[i]=b[i];
//cout<<"+"<<a[i]<<" ";
//cout<<endl;
}
void merge_sort(int l,int r)///归并
{
if(l<r)
{
int mid=(l+r)>>1;
merge_sort(l,mid);
merge_sort(mid+1,r);
merge(l,mid,r);
}
}
int main()
{
int n;
cin>>n;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
merge_sort(1,n);
cout<<ans<<endl;
return 0;
}