Подсчет количества инверсий в массиве, C ++

Инверсия в массиве a размера n называется парой (i,j), для которой она содержит i<j и a[i]>a[j]. Я пытаюсь реализовать функцию на C ++, которая подсчитывает количество инверсий в заданном массиве. Я следовал подходу «разделяй и властвуй», который просто изменяет алгоритм сортировки слиянием и работает за время O (n log n). Вот мой код:

long long int glob;

template< class T >
long long int merge( T *arr, int beg, int mid, int end ) {
  queue< int > left;
  queue< int > right;

  for( int i=beg; i<=mid; ++i ) {
    left.push( arr[i] );
  }
  for( int i=mid+1; i<=end; ++i ) {
    right.push( arr[i] );
  }

  int index=beg;
  int ret=0;

  while( !left.empty() && !right.empty() ) {
    if( left.front() < right.front() ) {
      arr[index++] = left.front();
      left.pop();
    } else {
      arr[index++] = right.front();
      right.pop();
      ret+=left.size();
    }
  }

  while( !left.empty() ) { arr[index++]=left.front();left.pop(); }
  while( !right.empty() ) { arr[index++]=right.front();right.pop(); }

  return ret;
}

template< class T >
void mergesortInvCount( T *arr, int beg, int end ) {
  if( beg < end ) {
    int mid = (int)((beg+end)/2);
    mergesortInvCount( arr, beg, mid );
    mergesortInvCount( arr, mid+1, end );
    glob += merge( arr, beg, mid, end );
  }
}

Для некоторых тестовых случаев он дает правильные результаты, но для некоторых других он дает неправильный результат. Я неправильно понял алгоритм или допустил ошибку при реализации? Может кто-нибудь мне помочь? Заранее спасибо.

Test case: 2 1 3 1 2
Correct: 4
Mine: 6

person Rontogiannis Aristofanis    schedule 10.10.2012    source источник
comment
Разве вы не можете научиться использовать отладчик, например? gdb- для отладки вашей программы (вы можете скомпилировать ее с g++ -Wall -g в Linux).   -  person Basile Starynkevitch    schedule 10.10.2012
comment
Не могли бы вы дать нам более конкретные описания ошибок (например, тестовые примеры и ожидаемые и фактические (неверные) результаты)?   -  person Grizzly    schedule 10.10.2012
comment
Я не знаю, какой алгоритм вы пытаетесь использовать (например, я не знаю, что должно содержать arr), но алгоритм, с которым я знаком, использует деревья BIT / деревья Фенвика.   -  person j_random_hacker    schedule 10.10.2012
comment


Ответы (2)


Я не проверил все шаги вашего кода, но ваша строка

if( left.front() < right.front() )

предложите мне, что в ветке else "ret" увеличивается не только когда a (j)> a (i), но и когда они равны, что не соответствует вашему описанию случая. Так что, возможно, вам стоит попробовать изменить строку, указанную выше, на:

if( left.front() <= right.front() )

С Уважением

person Bert te Velde    schedule 10.10.2012

Тест

if( left.front() < right.front() )

должно быть <=. Теперь вы перемещаете идентичные значения из правой половины в одну из левой половины, считая инверсии, которых нет (каждое такое вхождение учитывает ложные инверсии количества идентичных элементов в левой части). В вашем примере вам нужно дублировать пары, каждая из которых создает одну фантомную инверсию.

person Daniel Fischer    schedule 10.10.2012