算法导论归并排序那块的一道思考题:
1.merge的时候统计逆序数的个数。
#include < iostream >
using   namespace  std;
int  a[ 1000 ];
int  cnt;
int  merge( int  a[], int  p, int  q, int  z)
{   
    
int  l[ 1000 ],r[ 1000 ];
    l[
0 ] = q - p + 1 ;
    r[
0 ] = z - q;
    l[l[
0 ] + 1 ] = 0x7fffffff ;
    r[r[
0 ] + 1 ] = 0x7fffffff ;
    
int  i,j,k;
    
for (i = 1 ;i <= l[ 0 ];i ++ )
    {
        l[i]
= a[p + i - 1 ];
    }
    
for (j = 1 ;j <= r[ 0 ];j ++ )
    {
        r[j]
= a[q + j];
    }
    i
= 1 ;
    j
= 1 ;
    
for (k = p;k <= z;k ++ )
    {   
        
if (l[i] <= r[j])
            a[k]
= l[i ++ ];
        
else
        {   
            a[k]
= r[j ++ ];
            cnt
+= (l[ 0 ] - i + 1 );
        }
    }
    
return   0 ;
}
int  mergesort( int  a[], int  p, int  q)
{
    
if (p >= q)
        
return   0 ;
    
else  
    {
        
int  mid = (p + q) >> 1 ;
        mergesort(a,p,mid);
        mergesort(a,mid
+ 1 ,q);
        merge(a,p,mid,q);
    }
    
return   0 ;
}

int  main()
{   
    
int  n;
    
int  i;
    printf(
" 输入待排序的数字个数:\n " ); 
    scanf(
" %d " , & n);
    printf(
" 输入待排序数组:\n " );
    
for ( int  i = 1 ;i <= n;i ++ )
        scanf(
" %d " , & a[i]);
    printf(
" 待排序数组:\n " );
    
for (i = 1 ;i <= n;i ++ )
    {
        printf(
" %d  " ,a[i]);
    }
    printf(
" \n " );
    mergesort(a,
1 ,n);
    printf(
" 已排序数组:\n " );
    
for (i = 1 ;i <= n;i ++ )
    {
        printf(
" %d  " ,a[i]);
    }
    printf(
" \n逆序数为: " );
    printf(
" %d\n " ,cnt);
    system(
" pause " );
    
return   0 ;
}
2.离散化,扫描原始数列,若已插入某数字,设某数字离散化的位置为t,则t的cnt+1,维护树状数组。每次cnt+1之前之前算一下sum[n]-sum[t](n为离散化后数组中元素的个数),然后插入。
//PKU 2299
#include
< iostream >
#include
< algorithm >
#define  N 500010
using   namespace  std;
int  c[N];
int  a[N];
int  b[N];
int  n;
int  num = 1 ;
int  lowbit( int  t)
{
    
return  t & (t ^ (t - 1 ));
}
int  getsum( int  t)
{
    
int  sum = 0 ;
    
for ( int  i = t;i > 0 ;i -= lowbit(i))
        sum
+= c[i];
    
return  sum;
}
void  update( int  t)
{
    
for ( int  i = t;i <= num;i += lowbit(i))
        c[i]
++ ;
}
int  search( int  i)
{
    
int  mid,l = 1 ,r = num;
    
while (l <= r)
    {
        mid
= (l + r) / 2 ;
        
if (a[mid] == i)
            
return  mid;
        
else   if (a[mid] > i)
            r
= mid - 1 ;
        
else  l = mid + 1 ;
    }
}
int  main()
{
    
while (scanf( " %d " , & n) != EOF && n)
    {
        
for ( int  i = 1 ;i <= n;i ++ )
        {
            scanf(
" %d " , & a[i]);
            b[i]
= a[i];
        }
        num
= 1 ;
        sort(a
+ 1 ,a + 1 + n);
        
for ( int  i = 2 ;i <= n;i ++ )
        {
            
if (a[i] != a[i - 1 ])
                a[
++ num] = a[i];
        }

        memset(c, 0 , sizeof (c));
        
long   long  sum = 0 ;
        update(search(b[
1 ]));
        
for ( int  i = 2 ;i <= n;i ++ )
        {
            
int  t = search(b[i]);
            sum += getsum(num) - getsum(t);
            update(t);
        }

        printf( " %lld\n " ,sum);
    }
    
}