Link Cut
- link(u, v) - u становится сыном v, причем u корень.
- cut(u, v) - отрезать ребро.
- change(v, x) - поменять на вершине значение на x.
- min(u, v) - минимум на пути из u в v
Как все будет работать?
Некоторые ребра выделенные. У каждой вершины не более одного выделенного ребра в сына.
Введем операцию expose(v): Выделить все ребра от v до корня. И давайте для каждого выделенного пути хранить splay дерево.
Как только научимся делать данную операцию, покажем как через нее поулчить другие:
Изначально все веришны одиночные и в каждой веришне свое splay дерево
expose
void expose(v){
splay(v);
while(v != root){
u = v.parenth;
splay(u);
r = u.right;
r.pathparent = u;
отрезать поддерево r;
u.right = v;
v.pathparenth = null;
v =u;
}
}
То есть поднмаемся сверух вниз, отрезаем splay дерево, если надо, иначе поднимаемся выше и соединяем нужные splay
Использование expose для операций
- link(u, v) — делаем expose(u), expose(v), затем присоединяем (u) к (v) как ребёнка.
- cut(u) — делаем expose(u), отрезаем ребро между (u) и его родителем.
- change(v, x) — делаем expose(v), обновляем значение в вершине (v) (корне splay-дерева).
- min(u, v) — делаем expose(u), затем expose(v), теперь путь (u \to v) представлен в splay-дереве, на котором можно за (O(\log n)) получить минимум.
Важные моменты
- Каждый splay-узел хранит агрегированную информацию о поддереве (например, минимум).
- При splay-поворотах агрегаты обновляются.
- pathparent — ссылка на родителя вне splay-дерева (в исходном дереве).
- Вся работа со структурами происходит через splay-операции.