saprykin's blog

By saprykin, 3 years ago, In Russian

Привет, Codeforces!

В этом посте я бы хотел поделиться тем, как я пишу Дерево отрезков, объясню, почему я это делаю классом, а так же какие у этого плюсы и минусы.
Чтобы не быть голословным я бы хотел рассмотреть свое решение на конкретной задаче (осторожно, идеи к решению)

Код
Решение

Что в этом написании особенного

Основная моя идея в том, чтобы реализовать ДО как класс

Это позволяет использовать для двух деревьев отрезков более понятный интерфейс sgb.upd(l2, r2 + 1) sga.upd(l1, r1 + 1) sga.get(l1, r1 + 1) + sgb.get(l2, r2 + 1) вместо upd1(l1, r1 +1) upd2(l2, r2 + 1) и get1(l1, r1 + 1) + get2(l2, r2 + 1) А если количество деревьев переменно, то по другому это вроде не закодить(по крайней мере я не умею).

Другая не менее важная идея состоит в том, чтобы реализовать две функции каждого типа например get(int v, int l, int r, int L, int R) и get(int L, int R)

Я хочу получить значение на отрезке и не хочу думать о параметрах которые не влияют на запрос. Поэтому get(int v, int l, int r, int L, int R) является внутренним интерфейсом, который используется только для подсчета результата и не вызывается снаружи.

Так же я использую структуру, которая поддерживает приватные и публичные поля.

Это чисто эстетическое предпочтение, когда редактор подсказывает только те функции, которые могут быть вызваны снаружи.  против

Почему я пишу именно так

Однажды, когда я писал отбор в сириус, была задача в которой n исходная и n ДО не совпадали. И в функции запросов и обновления я писал неверное значение n. За время отбора я так и не раздебагал это. Как итог мне не хватило совсем чуть чуть баллов до прохода. После этой грустной истории я разработал для себя некий стандарт, которому стараюсь соответствовать.

Заключение

Плюсы

  1. Помогает не думать над тем, какой параметр передавать в запрос (Например в приведенной выше задаче, в одном случае размер равен n/2 + 1 а в другом n/2. Подобная ошибка в пару символов может стоить нескольких минут, а в худшем случае и десятков).
  2. Эстетично приятно.
  3. Пишется шаблонно (сначала mrg, потом build, дальше push и тд).
  4. Легко заменить. Нужно только изменить функцию mrg и поля у вершины.
  5. Подходит для задач, где нужно одинаковое ДО для нескольких массивов

Минусы

  1. Дольше работает. Во-первых, как известно статмасивы всегда лучше векторов по скорости, однако создать класс со статмасивом лично у меня не получилось (код крашается). Во-вторых вызов функции из класса вроде работает дольше, чем обычной функции
  2. Дольше пишется.

Вывод

Объективно минусы существенные по сравнению с плюсами. Однако я считаю, что мой способ написания имеет место быть. Он помогает избежать ошибок при написании и использовании не очень внимательным людям (к которым я, конечно же, отношусь). Если решение получает TL заменить vec t; на pii t[MAXN] не составит большого труда. А функции в основном решении уже стоят где надо и с правильными параметрами.

Я никого не призываю начинать писать код по другому. Лишь хочу поделиться своими знаниями. Спасибо за внимание, и высокого рейтинга!

  • Vote: I like it
  • +4
  • Vote: I do not like it