Трюк для DSU (disjoint set union), с которым я недавно столкнулся:
У нас есть элементы, над которыми нужно выполнять два типа запросов:
- Union — объединить множества, содержащие элементы v1 и v2.
- Add — для всех i в множестве, содержащем элемент v, прибавить некоторое значение x к a[i].
Чтобы поддерживать это эффективно, можно хранить неявные модификации в вершинах — аналогично ленивым обновлениям (lazy propagation) в дереве отрезков, но без явной передачи изменений вниз.
При запросе Add мы находим корень дерева, содержащего вершину v, и добавляем модификацию в этот корень. Когда нужно получить реальное значение a[i], мы сначала выполняем сжатие пути к корню и применяем модификации от корня. Во время сжатия пути (в процессе рекурсивного переподключения вершин) мы также применяем модификацию родителя к текущей вершине.
Для операции Union можно действовать двумя способами:
- Создать новую виртуальную вершину, которая станет родителем обоих компонентов.
- Прикрепить один корень к другому и применить обратную модификацию к поддереву, которое становится потомком.
Второй способ немного сложнее в реализации, особенно если модификации более сложные.








