题目大意
给定N个数(没有相同的值),对N个数进行升序排序,每次只能交换相邻的两个数,问最少需要多少次交换才能够让N个数成为升序排列的
题解
就是逆序对问题,如果a[i]>a[j](i<j)则就是一个逆序对,此题可以用归并排序解决,也可以树状数组,不过我是当树状数组来练习的。此题数据有点大0 ≤ a[i] ≤ 999,999,999,所以需要把N个数进行离散化,因为我们对每个数的值并不感兴趣,只需要知道每个数的大小即可。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 500005 using namespace std; typedef struct { long id; long t; } NODE; NODE a[MAXN]; long long c[MAXN]; long f[MAXN]; long n; long lowbit(long x) { return x&-x; } long sum(long x) { long ret=0; while(x>0) { ret+=c[x]; x-=lowbit(x); } return ret; } void add(long x,long d) { while(x<=n) { c[x]+=d; x+=lowbit(x); } } bool cmp(NODE x,NODE y) { return x.t<y.t; } int main(void) { long i; long long ans; while(scanf("%ld",&n)==1&&n) { for(i=1; i<=n; i++) { scanf("%ld",&a[i].t); a[i].id=i; } sort(a+1,a+n+1,cmp); memset(c,0,sizeof(c)); for(i=1; i<=n; i++) f[a[i].id]=i; ans=0; for(i=n; i>=1; i--) { add(f[i],1); ans+=sum(f[i]-1); } printf("%I64d\n",ans); } return 0; }