Блог пользователя Mynewhandle-N.Y

Автор Mynewhandle-N.Y, 11 лет назад, По-русски

Hi !

Предлагаю всем поучаствовать на олимпиаде проходящей на сайте neerc.ifmo.ru

Начало : ВуАлЯ!

Предлагаю здесь обсудить задачи.

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

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

Могут ли в четвертой задаче два сегмента пересекаться?

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

Уже закончилось, пожалуй. Как решать последние 3 задачи?
Классный контест.

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

    Во второй почти всегда работает простой поиск базовых циклов, поэтому делаем 50 раз из рандомной вершины, мешаем ребра...:)

    Третью делал ленивым апдейтом.

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

      Ну я во 2 тоже самое написал, но как-то это не то...
      А можно подробнее про ленивый апдейт?

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

      а можно пояснить зачем рандомность нужна? разве просто поиск циклов может здесь неправильно работать?

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

        Задача B:

        Если в графе любые два цикла имеют не более 1-ой общей вершины, то их не более 3-ех. Иначе таких циклов не более двух, так как оба цикла плюс их объединение без учета "перемычки" дадут три различных варианта. Для решения будем использовать базовый поиск циклов с помощью DFS, не забывая каждый раз обновлять ответ при нахождении цикла большей длины.

        Первый случай мы обработаем одним запуском DFS. Рассмотрим второй случай подробнее:

        Если применять базовый поиск циклов через DFS, то мы можем обнаружить два маленьких циклах, а их объединение — нет. Существует несколько вариантов поиска "большого" цикла:

        • Завести массив пометок t, изначально обнуленный. Далее, если DFS нашел цикл, то пометим все вершины цикла в массиве t единицей, то есть t[cycle[i]]=1. Но если эта вершина уже была помечена, то поставим метку "2". Получаем t[cycle[i]]=t[cycle[i]]==1?2:1 . Таким образом, чтобы за второй запуск DFS мы нашли "большой" цикл, будем игнорировать ребра соединяющие вершины с меткой "2". Реализация

        • Теперь, что касается рандома. Заметим, что от порядка ребер зависит по какому циклу пойдет DFS. Если ребро ведущее в "маленький" цикл раньше ребра ведущего по "большому" циклу в списке ребер, то мы обнаружим два "маленьких" цикла, иначе один "большой" и один "маленький" циклы. Данные ситуации являются равновероятными, то есть 1/2 шанс исхода каждого события. Тогда сделаем 2 запуска DFS из первой вершины, и перед каждым запуском перемешаем списки ребер для каждой вершины. Такое решение гарантирует, что хотя бы один раз DFS пойдет по "большому" циклу. Реализация

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

    Вторую делал так: сделаем три итерации алгоритма — найдём произвольный цикл, попробуем обновить ответ. Затем проверим можно ли из какой-либо вершины этого цикла построить цепь, которая закончится также в одной из вершин цикла. Если такая цепь нашлась, то мы имеем 3 цикла, и после очередного обновления ответа завершим программу. Иначе если такой цепи не нашлось, значит первоначальный найденный цикл не имеет общих рёбер/вершин с каким-либо ещё циклом => мы можем удалить вершины, ему принадлежащие, из графа.

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

это неловкое чувство, когда написал адовое решение в С, думая, что надо считать сумуу (i%n)*cnt[i], а не (n%i)*cnt[i]

а так клевый контест, пожалуй, лучший за последнее время

»
11 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится
»
11 лет назад, # |
Rev. 4   Проголосовать: нравится 0 Проголосовать: не нравится

Кто-нибудь знает, почему на контесте решение B (http://pastebin.com/kycSS9gQ) заходит на 60 баллов, а здесь, на дорешке CF на полный балл?

UPD

Видимо dfs хватает RE из-за переполнения стека( Как-то некрасиво получилось.

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

Объясните, пожалуйста, решение C и D на 100.

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

    Решение С за TsqrtN:

    Отвечать на запрос будем таким образом: Втупую посчитаем ответ для тех которые меньше корня из n. Теперь нужно посчитать вклад тех k, которые больше корня из n, то есть сумму по всем k: n % k = n — (n / k) * k. Первое слагаемое считается очевидно, а сумму второго будем считать так, заметим, что всего корень из n различных значений n / k. Теперь заведем массив a[i] = count * i, где count — количество хедкрабов с таким i. Разделим сумму на корень из n блоков с одинаковым n / k. Для конкретного блока n / k = c, теперь нужно посчитать сумму таких k, которые деля нацело n дают частное c. Это сумма на отрезке [st, en) массива a, где st — минимальное k, такое что n / k <= c, а en минимальное k, такое что n / k < c. Утверждается, что st = n / (c + 1) + 1, но можно было искать и бинпоиском. Сумму на таком отрезке будем считать с помощью префикс сумм и sqrt-декомпозиции.

    При запросах на добавление и удаление будем пересчитывать массив a, за корень из n, применяя sqrt-декомпозицию.

    Также проходило решение с фенвиком вместо sqrt-декомпозиции.

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

      Это одно из самых непонятных объяснений решений из тех, которые я видел.