计算逆序个数,方法参照《算法设计》(美)克林伯格,5.3节
#include < iostream >
using namespace std;
#define M 500000
int a[M],b[M],ca[M],cb[M];
int main()
{
int * x, * y, * z, * cx, * cy,n,i,j,k,s,e,t;
__int64 ans;
while (scanf( " %d " , & n) && n)
{
memset(ca, 0 , sizeof (ca));
for (i = 0 ;i < n;i ++ )scanf( " %d " , & a[i]);
for (i = 0 ,j = 2 ,x = a,y = b,cx = ca,cy = cb;;j *= 2 )
{
for (k = 0 ;k < n;k += j)
{
s = t = k,e = k + j / 2 ;
while ((s < k + j / 2 ) && e < (k + j) && e < n)
{
if (x[s] < x[e])y[t] = x[s],cy[t ++ ] = cx[s ++ ];
else if (x[s] > x[e])y[t] = x[e],cy[t ++ ] = cx[e ++ ] + k + j / 2 - s;
}
while (s < k + j / 2 && s < n)y[t] = x[s],cy[t ++ ] = cx[s ++ ];
while (e < (k + j) && e < n)y[t] = x[e],cy[t ++ ] = cx[e ++ ];
}
z = x,x = y,y = z;
z = cx,cx = cy,cy = z;
if (j >= n) break ;
}
for (i = 0 ,ans = 0 ;i < n;i ++ )ans += cx[i];
printf( " %I64d\n " , ans);
}
return 0 ;
}