Блог пользователя Ocean1001

Автор Ocean1001, 13 лет назад, По-русски

Дана довольно банальная задача. Дан массив состоящий из N чисел (N<=10^5). Нужно для каждого числа вывести кол-во чисел, которые лежат справа и которые меньше его самого. Помогите пожалуйста как решать подобную задачу.

  • Проголосовать: нравится
  • +1
  • Проголосовать: не нравится

»
13 лет назад, скрыть # |
 
Проголосовать: нравится -21 Проголосовать: не нравится

Строишь декатово дерево по явному ключу (с поддержкой размера поддеревьев), двигаясь справа на лево. Соответственно сплитишь по текущему ключу и смотришь, сколько элементов в левом дереве.

»
13 лет назад, скрыть # |
 
Проголосовать: нравится +6 Проголосовать: не нравится

Используешь дерево отрезков. Если числа большие (<= 10 ^ 9), то сжимаешь координаты, потом идешь справа налево, и для каждого числа a[i] берешь сумму от 1 до a[i] — 1, и не забудь обновить дерево update (a[i], 1).

»
13 лет назад, скрыть # |
Rev. 4  
Проголосовать: нравится -10 Проголосовать: не нравится

в деревьях не силен, к сожалению, но первое что пришло в голову() возможно не работает и не красиво , просьба не ругать, а лучше указать на ошибки а также более хорошее , оптимальное и правильное решение

mass[]:=1..N;

for (i=0 i<N i++)
  { num=mass[i];
    
	for (j=i+1 j<N j++)
            { if(mass[j]<num)  count++ ;
             } 
    
  mass2[i]=count;count=0;
                  

  print mass[i] : mass2[i] /n;

   }
»
13 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Предлагаю такой алгоритм: Идем по массиву с конца одновременно запихивая числа в multiset, до запихивания очередного числа проверяем сколько в multiset'е чисел меньше текущего, запоминаем ответы.

O (n log n).

Вот только не помню как узнать сколько в multiset чисел меньших какого-то за O(log n).

»
13 лет назад, скрыть # |
 
Проголосовать: нравится +7 Проголосовать: не нравится

Эта задача аналогична подсчету числа инверсий в массиве, только здесь мы считаем инверсии для каждого элемента, поэтому наравне с использованием различных деревьев можно использовать модификацию сортировки слияния по убыванию массива пар <элемент, индекс в изначальном массиве> (индекс нужен для восстановления ответа).

Модификация известная и состоит в следующем: когда мы сравниваем текущие элементы левого и правого массивов left[i] и right[j], то при left[i] > right[j] все дальнейшие элементы правого массива также меньше (мы сортируем по убыванию), поэтому мы прибавляем к ответу для left[i] число (right.length — j + 1).

»
13 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Если за O(n logn) устроит, то так:

std::vector<size_t> GetAns(const std::vector<int>& a)
{
    const size_t n = a.size();
    std::vector<size_t> b(n);
    std::multiset<int> r;
    for (size_t i = n; i > 0; i--)
    {
        b[i - 1] = std::distance(r.begin(), r.lower_bound(a[i - 1]));
        r.insert(a[i - 1]);
    }
    return b;
}

UPD: это неправильно, ошибся с std::distance.