此题就是求冒泡的次数,用冒泡做时间比较长,用树状数组做比较快
#include<stdio.h>
int num[1024],n;
int main( )
{
while( scanf( "%d",&n ) != EOF )
{
for( int i = 0; i < n; ++i )
scanf( "%d",&num[i] );
int count = 0;
for( int i = 0,f = 0; i < n - 1; ++i )
{
f = 0;
for( int j = 0; j + 1< n - i; ++j )
{
if( num[j+1] < num[j] )
{
int c = num[j+1];
num[j+1] = num[j];
num[j] = c;
f = 1;
++count;
}
}
if( !f )
break;
}
printf( "%d\n",count );
}
return 0;
}
下面是用树状数组+逆序数的求法,这里就是把一个数插入到一个已经排好的的有序数列中,用plus来告诉来更新后面的点标记后面的数前面有多少个比他小的数,然后再用sum求有多少个比x小的数,而i表示目前数列中的总数,i-sum( x-1 )就算出有多少比x大的数,这样就算出x要交换多少次,s算出来即是最终结果了;
#include<stdio.h>
#include<string.h>
#define lowbit( x ) (x)&(-x)
int num[1024],n;
void plus( int x )
{
while( x <= n )
{
++num[x];
x += lowbit( x );
}
}
int sum( int x )
{
int s = 0;
while( x )
{
s += num[x];
x -= lowbit( x );
}
return s;
}
int main( )
{
while( scanf( "%d",&n ) != EOF )
{
memset( num,0,sizeof( num ) );
int s = 0;
for( int i = 0; i < n; ++i )
{
int x;
scanf( "%d",&x );
plus( x );
s += ( i - sum( x - 1 ) );
}
printf( "%d\n",s );
}
return 0;
}