Rope (23 апреля 2021)
- Кодим
- Пишем персистентное дерево отрезков.
- Интерфейс Rope: insert(i,x), erase(i), get(i), split, merge, rotate
- Известные реализации (деревья по неявному ключу): treap, AVL, RB, 2-3
- Новые реализацяии: skip-list, splay, корневая
- Skip-list
- List: умеет делать Add и Del за O(1), если уже известно место; сложности с Find.
- Добавим несколько уровней: ссылки вперёд на 2, на 4, на 8 и т.д. (ровно на степень двойки)
- Find работает, но после Insert длины (степени двойки) сломаются. Поэтому будем хитрее: каждый элемент есть на уровне выше с вероятностью 1/2.
- Find. Add. Del.
- Не забыть: (а) фиктивный элемент, общий для всех списков; (б) мы не храним индексы, храним только длины рёбер
- Splay-tree
- Собственно дерево: add и del, splay = zig-zig + zig-zag + last one.
- Вращения: zig-zag = double = 2 signle, zig-zig = 2 single в другом порядке.
- time(add) = time(splay) = ∑ time(zig-zig), осталось оценить только амортизированное время zig-zig
- Теорема об амортизированном времени работы. Потенциал = ∑ log(Sv) (Sv − размер поддерева).
- Более тонкое время работы: ∑ ti = O(∑ ki log(m/ki))
- Персистентность и отцы
- Отцы не дружат с персистентностью. Но от них почти всегда можно избавиться.
- Fat Nodes позволяет поддерживать и отцов тоже.
− Перерыв −
- SQRT-decomposition
- Простая корневая: минимум на отрезке.
- Что делать, если нужно вставлять и удалять элементы? Два разных решения: split/merge; rebuild.
- Удобная версия корневой: только split и rebuild.
- Отложенные операции: сортированный массив + добавление новых элементов + количество элементов от x до y. Концепция: есть казалось бы неизменяемая структура, сделаем её изменяемой.
- Корневая по запросам: более общий взгляд на предыдущую идею.
- Статическая оптимальность
- Формулировка задачи с вероятностями и матожиданием.
- Решение Кнутом за O(n2).