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

Автор pcheloveks, история, 6 месяцев назад, По-русски

Трюк для DSU (disjoint set union), с которым я недавно столкнулся:

У нас есть элементы, над которыми нужно выполнять два типа запросов:

  1. Union — объединить множества, содержащие элементы v1 и v2.
  2. Add — для всех i в множестве, содержащем элемент v, прибавить некоторое значение x к a[i].

Чтобы поддерживать это эффективно, можно хранить неявные модификации в вершинах — аналогично ленивым обновлениям (lazy propagation) в дереве отрезков, но без явной передачи изменений вниз.

При запросе Add мы находим корень дерева, содержащего вершину v, и добавляем модификацию в этот корень. Когда нужно получить реальное значение a[i], мы сначала выполняем сжатие пути к корню и применяем модификации от корня. Во время сжатия пути (в процессе рекурсивного переподключения вершин) мы также применяем модификацию родителя к текущей вершине.

Для операции Union можно действовать двумя способами:

  1. Создать новую виртуальную вершину, которая станет родителем обоих компонентов.
  2. Прикрепить один корень к другому и применить обратную модификацию к поддереву, которое становится потомком.

Второй способ немного сложнее в реализации, особенно если модификации более сложные.

Spoiler

Полный текст и комментарии »

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