求对一列数排序所需的最少交换次数,也就是求逆序对个数
首先可以用归并排序做,比较简单
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=500010;
long long a[maxn],b[maxn],ans;
int n;
void Merge(int L,int R)
{
if(L>=R)
return;
int mid=(L+R)>>1;
Merge(L,mid);
Merge(mid+1,R);
int i=L,j=mid+1,now=0;
while(i<=mid&&j<=R)
{
if(a[i]>a[j])
{
ans+=mid-i+1;
b[now++]=a[j++];
}
else
b[now++]=a[i++];
}
while(i<=mid)
b[now++]=a[i++];
while(j<=R)
b[now++]=a[j++];
now=0;
for(i=L;i<=R;i++)
a[i]=b[now++];
}
int main()
{
while(scanf("%d",&n)&&n)
{
ans=0;
for(int i=0;i<n;i++)
scanf("%lld",&a[i]);
Merge(0,n-1);
printf("%I64d\n",ans);
}
return 0;
}
第二种方法是找逆序对的方法,用树状数组进行更新记录即可
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500010;
struct node
{
long long val;
int index;
bool operator <(const node &a)const
{
return val<a.val;
}
}a[maxn];
int n;
long long c[maxn*3],index[maxn];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val)
{
for(int i=x;i<maxn*2;i+=lowbit(i))
c[i]+=val;
}
long long sum(int x)
{
long long ans=0;
for(int i=x;i>0;ans+=c[i],i-=lowbit(i));
return ans;
}
int main()
{
while(scanf("%d",&n)&&n)
{
memset(c,0,sizeof(c));
memset(index,0,sizeof(index));
for(int i=1;i<=n;i++)
{
scanf("%I64d",&a[i].val);
a[i].index=i;
}
sort(a+1,a+n+1);
index[a[1].index]=1;
for(int i=2;i<=n;i++)
{
if(a[i].val!=a[i-1].val)
index[a[i].index]=i;
else
index[a[i].index]=index[a[i-1].index];
}
long long ans=0;
for(int i=1;i<=n;i++)
{
update(index[i],1);
ans+=sum(n)-sum(index[i]);
}
printf("%I64d\n",ans);
}
return 0;
}