水呀水
学了merge_sort的归并排序求逆序对,对于求逆序对方法,冒泡排序法是相邻两个依据大小交换,每次交换均表示有一对逆序对,经过实验证明超时(:з」∠)
而归并相比则快得多233
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
·题目描述 Description
给定一个序列a1,a2,…,an,如果存在i小于j并且ai>aj,那么我们称之为逆序对,求逆序对的数目
数据范围:N<=105。Ai<=105。时间限制为1s。
·输入描述 Input Description
第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。
·输出描述 Output Description
所有逆序对总数.
·样例输入 Sample Input
4
3
2
3
2
·样例输出 Sample Output
3
感觉还是比较好懂的
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
typedef long long ll;
using namespace std;
const int sz = 100010;
ll a[sz],tmp[sz];
ll ans,n;
inline void merge(ll l,ll m,ll r)
{
ll i=l;
ll j=m+1;
ll k=l;
while(i<=m&&j<=r)
{
if(a[i]>a[j])
{
tmp[k++]=a[j++];
ans+=m-i+1;
}
else
tmp[k++]=a[i++];
}
while(i <= m) tmp[k++]=a[i++];
while(j <= r) tmp[k++]=a[j++];
for(int i=l;i<=r;i++)
a[i] = tmp[i];
return;
}
inline void merge_sort(ll l,ll r)
{
if(l<r)
{
ll m=(l+r)>> 1;
merge_sort(l,m);
merge_sort(m+1,r);
merge(l,m,r);
}
return;
}
int main()
{
scanf("%lld",&n);
for(ll i=0;i<n;i++)
scanf("%lld",&a[i]);
merge_sort(0,n-1);
printf("%lld\n",ans);
return 0;
}