C++写数组的反转计数指示, 数组排序的距离。如果数组已经排序,则反转计数为0,但是如果数组以相反顺序排序,则反转计数为最大值。 如果a [i]> a [j]且i <j,则两个元素a [i]和a [j]构成一个倒置,并输出每一个倒置组合
时间: 2023-12-27 20:03:33 浏览: 68
C++链表的反转
好的,让我来解答这个问题。
首先,反转计数指示是指在一个数组中,有多少对元素是逆序排列的。而数组排序的距离是指将一个数组排序后,与原数组的不同之处。
以下是C++代码实现:
```C++
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e5+10;
int n;
int a[N],tmp[N];
int tr[N];
int lowbit(int x) //树状数组
{
return x&-x;
}
void add(int x,int c)
{
for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
int sum(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
long long merge_sort(int l,int r) //归并排序求逆序对
{
if(l>=r) return 0;
int mid=l+r>>1;
long long res=merge_sort(l,mid)+merge_sort(mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r)
{
if(a[i]>a[j])
{
res+=(mid-i+1);
tmp[k++]=a[j++];
}
else tmp[k++]=a[i++];
}
while(i<=mid) tmp[k++]=a[i++];
while(j<=r) tmp[k++]=a[j++];
for(int i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
memcpy(tmp,a,sizeof a);
sort(tmp+1,tmp+n+1); //排好序的数组
int len=unique(tmp+1,tmp+n+1)-tmp-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(tmp+1,tmp+len+1,a[i])-tmp;
long long ans=merge_sort(1,n);
printf("The reverse count is: %lld\n",ans);
memset(tr,0,sizeof tr);
long long res=0;
for(int i=1;i<=n;i++)
{
res+=i-1-sum(a[i]);
add(a[i],1);
}
printf("The distance is: %lld\n",min(res,1ll*n*(n-1)/2-res));
printf("The reverse pairs are:\n");
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[i]>a[j]) printf("(%d,%d)\n",i,j);
return 0;
}
```
这段代码实现了归并排序求逆序对,树状数组求逆序对个数,以及输出所有逆序对的组合。
希望能对你有所帮助!
阅读全文