归并排序求逆序对:
代码如下:
#include<bits/stdc++.h>
using namespace std;
int a[1005];//存放数组
int rr[1005];//辅助数组,额外开销
int n,ans;
void build(int l,int r)
{
int mid = (l + r) / 2;
if (l == r) return;//只有一个数的时候返回
build(l, mid);//不断分割
build(mid+1, r);
int x = l, y = mid+1, z = l;
while (x <= mid && y<=r)
{
if (a[x] < a[y])
rr[z++] = a[x++];
else
rr[z++] = a[y++], ans += mid - x + 1;//逆序对
}
while (x <= mid)
rr[z++] = a[x++];
while (y <= r)
rr[z++] = a[y++];
for (int i = l;i <= r;i++)
a[i] = rr[i];
}
int main()
{
cin>>n;
for (int i = 0; i < n; i++)
scanf("%d", a+i);
build(0, n-1);
cout<<ans<<endl;
}
紫书算法:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+6;
int ans=0;
int a[maxn];
int rr[maxn];
void sort_merge(int l,int r)
{
if (r - l > 1)
{
int mid= (l + r)>>1;
sort_merge(l, mid);
sort_merge(mid, r);
int x = l, y = mid, z = l;
while (x < mid || y < r)//如果满足说明有一部分没有合并
{
if ( y>= r || (x < mid && a[x] <= a[y])) rr[z++]=a[x++];
//(y>=r)说明右边合并完了,进来while循环代表没有合并完
//所以直接可以合并左边,(x<mid&&a[x]<=a[y])说明左边都没合并完,直接合并左边
else rr[z++] = a[y++],ans += mid-x;//ans代表逆序对。
}
for(int i=l;i<r;i++)
a[i]=rr[i];
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(a,0,sizeof a);
memset(rr,0,sizeof rr);
ans=0;
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
sort_merge(0, n);//区间为0-n的左闭右开
printf("%d\n", ans);
}
}