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

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

Только что закончилась восьмая личная интернет олимиада по задачам ИОИП, которая прошла вчера. Предлагаю обсудить здесь задачи. Задачи

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

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Сдал задачу на 4:59 :D

»
12 лет назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

Что-то результатов еще нет:(

»
12 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

Mr.Mike when you will add problems in gyms? We are waiting for you...

»
12 лет назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится

Как решали задачу E на 100?

  • »
    »
    12 лет назад, # ^ |
    Rev. 4   Проголосовать: нравится +14 Проголосовать: не нравится

    Ну вот лично я решал так:

    Будем для каждого a[i] считать число элементов таких, что a[i] < a[j] и i > j, то есть инверсии по сути. Это можно сделать деревом Фенвика, например. Затем заметим, что после каждого прохода Гарри у каждого a[i] это число либо уменьшается на 1, если больше 0, либо остается 0. То есть за k ходов все эти значения уменьшатся на k, если больше k, либо станут = 0.

    Теперь нам нужно по этим данным восстановить исходную перестановку. Можно это сделать по-разному, например деревом отрезков для суммы на отрезке, но так как ограничения позволяют вполне — можно схалявить и написать того же фенвика и бинпоиск. Просто мы будем расставлять элементы в порядке увеличения их значения. То есть сначала мы найдем позицию для 1, потом для 2, 3 и так далее... Просто бинпоиском ищем нашу позицию и фенвиком узнаем — сколько позиций до нашей не занято — там однозначно будут стоять бОльшие числа.

    Мой код

    • »
      »
      »
      12 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +16 Проголосовать: не нравится

      Задача становится легче, если постараться ответить на вопрос — какое число будет стоять на первом месте?
      К примеру, для 20 чисел и 10 проходов? Легко понять, что это будет минимальное число из первых 11-ти. А на втором месте? Минимальное число из первых 12-ти, кроме того, что уже стоит на первом месте.
      Все. Строим дерево отрезков на поиск минимума, в котором еще храним порядковый номер числа. Делаем запрос на минимум для первого числа ( от 1 до 11-го), кидаем его в ответ, меняем в дереве отрезков его на максимальное возможное, пересчитываем дерево. Для второго числа запрос на минимум на интервале от 1 до 12-го. И т.д.

      • »
        »
        »
        »
        12 лет назад, # ^ |
          Проголосовать: нравится +6 Проголосовать: не нравится

        Крутая идея) А если вместо дерева отрезков использовать priority_queue, то код вообще короче некуда выходит)

»
12 лет назад, # |
  Проголосовать: нравится +2 Проголосовать: не нравится

а как решать C?

  • »
    »
    12 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

    Сначала поймем — когда ответ IMPOSSIBLE. По очевидным причинам так происходит, когда у нас больше одной вершины со степенью 1. Единственное исключение — случай, когда у нас всего 2 вершины — такого, кстати, в тестах не было почему-то.

    Теперь, собственно, само решение:

    Известно, что gcd(x, x + 1) = 1. Используем это. Нам нужно обойти наш граф так, чтобы у каждой вершины (кроме начальной) были ребра с числами x и x + 1. Это сделать очень просто — идем dfs-ом из вершины со степенью 1, если такая есть, иначе из любой. И просто проставляем цифры по порядку от 1 до m. Это всегда будет верно, потому что, если степень вершины > 1, то мы из неё сможем перейти дальше, а если мы пришли в неё по ребру x, то куда-то из неё мы пойдем по ребру x + 1.

»
12 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

Что насчет D? Просто нужно было аккуратно юзать кучу?

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Сортируем массив. Понятно, что теперь минимальная разница будет между соседними элементами. Проходим по нему и пихаем в дерево разницы между соседними элементами, сравнивая как сказано в условии. Теперь просто на каждой из n итераций берём и удаляем лучшие 2 элемента из дерева. Пусть из {a, b, c, d} мы выбрали (b, c). Тогда удаляем из дерева a-b, b-c и c-d (учитывая крайние случаи), вставляем a-d. Только нужно ещё поддерживать для каждого элемента указатели к соседним неудалённым элементам.

»
12 лет назад, # |
  Проголосовать: нравится +16 Проголосовать: не нравится

Я наконец-то выложил результаты, архивы и разборы. Извиняюсь перед сообществом за такие задержки :)

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Простите, но это всё-таки не седьмая, а восьмая олимпиада