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

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

Пока некоторые люди страдают от нехватки контестов, я решаю задачки из архивов (:


Сегодня открыл эту задачу: http://informatics.mccme.ru/moodle/mod/statements/view3.php?id=597&chapterid=753#1

Вроде тема курса намекает на то, что ее нужно решать через Range Maximum Query.
Я так и делаю, но что-то не получается.

Кратко опишу свой алгоритм:

1) строим дерево из N элементов (все нули)
2) Каждый запрос, в зависимости от его типа, обрабатываем особым образом:
    2.1) Если запрос первого типа, то вызываем RMQ(L,R). Если результат 0, то ни один элемент этого
           отрезка не входит ни в одну группу - объединяем.
           2.1.1) Что значит объединяем? Всем элементам из данной группы присваиваем одно и то же
                       значение - номер группы (номер группы - счетчик, увеличиваем его с появлением каждой новой группы)
           2.1.2) При каждом изменении значения элемента делаем update данного элемента в дереве.
    2.2) Если запрос второго типа, то проверяем:
           2.2.1) Если значение элемента - 0, то элемент не принадлежит ни одной группе, выводим "0 0"
           2.2.2) Если значение элемента больше 0, то:
                     2.2.2.1) Проходим вправо - ищем правую границу, попутно обнуляя элементы и делая
                                  update дерева. Аналогично ищем левую границу
                     2.2.2.2) Выводим границы

Приветствуются прямые указания на ошибки и хорошие тесты, которые завалят программу.

Заранее спасибо!
Теги rmq
  • Проголосовать: нравится
  • +2
  • Проголосовать: не нравится

13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
По-моему, ее проще всего решить set'ом. И никаких структур тогда самому писать не придется.

В сете достаточно хранить пары чисел - начало и конец каждой группы. Только надо учесть что если несколько отрезков подряд не принадлежат никакой группе, то мы их объединим в фиктивную группу и тоже будем хранить только номер левого и правого отрезка.
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

Вы бы писали вердикт и тест. Я предполагаю TL, т.к. алгоритм неправильный, в нем первая операция выполняется за n*log(n), т.е. в сумме n^2*log(n), что медленно. Требуются интервальные модификации, позволяющие присваивать отрезку значение за log(n).
UPD. со второй операцией ровно та же проблема.
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Тесты я не вижу - там закрытая система.

    Сейчас у меня WA 5.
    • 13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Я имел в виду номер теста - он иногда тоже помогает. В любом случае ваш алгоритм слишком медленный. Вот тут можно почитать подробнее про изменение на отрезке.
      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        к слову, ее можно решить используя просто дерево отрезков (без изменения на отрезке) или дерево фенвика
13 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

А где-то уже была тема про эту задачу, помню, что я ее решил с помощью сета отрезков, очень просто делается

А вот и быдлокод на C++ (форматирование съехало): http://pastebin.com/j2zNEDUv
13 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится
Теперь тест:
100000 100000
1 1 100000
2 50000
1 1 100000
2 50000
1 1 100000
2 50000
...
1 1 100000
2 50000

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

Т.к  автор пишет на паскале не думаю что есть возможность воспользоваться C++ сетом

Если вдруг поможет (готовое решение с чистым деревом отрезков) http://pastebin.com/pg13fDgk (хотя тоже на си)

13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Люди pastebin не работает((
  • 13 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится
    Да, он упал почти сразу после того, как я загрузил решение (:
    Оно ему, как и freopen'у, сильно не понравилось :D