Дерево Фенвика для некоммутативных операций — различия между версиями
м (→Обновление элемента) |
м (rollbackEdits.php mass rollback) |
||
(не показано 12 промежуточных версий 4 участников) | |||
Строка 3: | Строка 3: | ||
== Обновление элемента == | == Обновление элемента == | ||
− | Как и ранее, для обновления элемента в дереве нужно изменить все, что хранит результат операции с этим элементом. Но теперь нельзя просто применить операцию <tex> G </tex> (далее | + | Как и ранее, для обновления элемента в дереве нужно изменить все, что хранит результат операции с этим элементом. Но теперь нельзя просто применить операцию <tex> G </tex> (далее будем использовать мультипликативную нотацию) ко всем нужным элементам дерева. Пусть мы хотим изменить <tex> a_i </tex> на <tex> a_i' = a_i \cdot d </tex>, в данный момент обновляем элемент дерева с индексом <tex> j </tex>. Вместо <tex> a_{j \& (j + 1)} \cdot \ldots a_i \cdot d \cdot \cdot \ldots \cdot a_j </tex> мы получим <tex> a_{j \& (j + 1)} \cdot \ldots a_i \cdot \ldots \cdot a_j \cdot d </tex> (так как больше нельзя переставлять элементы местами в операции на отрезке, ответ будет неверен). |
− | + | Для решения этой задачи нужно удалить отрезок после изменяемого элемента, изменить элемент, после чего добавить этот отрезок снова. | |
− | + | {{Теорема | |
+ | |statement= | ||
+ | Пусть <tex> s_i = a_1 \cdot a_2 \cdot \ldots \cdot a_i </tex> — результат выполнения операции на префиксе <tex> i </tex>; <tex> s_{i, j} = s_i^{-1} \cdot s_j </tex> — результат ее выполнения на отрезке <tex> [i; j] </tex>. Тогда элемент дерева с индексом <tex> j </tex> обновляется как <tex> t_j' = t_j \cdot s_{i, j}^{-1} \cdot d \cdot s_{i, j} </tex>. | ||
− | <tex> | + | |proof= |
+ | Может показаться, что этот способ не работает, так как <tex> s_i </tex>, возможно, уже было изменено, а <tex> s_j </tex> — еще нет, значит, мы удаляем не тот отрезок, который должны удалить. Убедимся, что на самом деле все обновляется правильно. Учитывая, что <tex> (x \cdot y)^{-1} = y^{-1} \cdot x^{-1} </tex>, получаем: | ||
− | <tex> s_{i, j} | + | <tex> s_{i, j}' = (s_i \cdot d)^{-1} \cdot s_j = d^{-1} \cdot s_i^{-1} \cdot s_j = d^{-1} \cdot s_{i, j} </tex>; |
− | Пусть в дереве <tex> n </tex> элементов. Так как для каждого из <tex> O(\log | + | <tex> {s_{i, j}'}^{-1} \cdot d \cdot s_{i, j}{'} = (d^{-1} \cdot s_{i, j})^{-1} \cdot d \cdot d^{-1} \cdot s_{i, j} = s_{i, j}^{-1} \cdot d \cdot d \cdot d^{-1} \cdot s_{i, j} = s_{i, j}^{-1} \cdot d \cdot s_{i, j} </tex>, то есть элемент дерева изменяется на правильное значение. |
+ | }} | ||
+ | === Время работы === | ||
+ | Пусть в дереве <tex> n </tex> элементов. Так как для каждого из <tex> O(\log {n}) </tex> изменяемых элементов дерева мы совершаем дополнительно запрос суммы на отрезке(а он работает за <tex> O(\log {n}) </tex> операций), то асимптотическое время работы обновления элемента ухудшается до <tex> O(\log^2{n}) </tex>. | ||
− | == | + | == Пример == |
+ | Пусть есть массив из пяти матриц <tex> a </tex>: | ||
− | + | <tex> \begin{array}{c||c||c||c||c} \begin{pmatrix} 1 & 0 \\ 0 & 2 \end{pmatrix} & | |
+ | \begin{pmatrix} 1 & 2 \\ 0 & 1 \end{pmatrix} & | ||
+ | \begin{pmatrix} 0 & 1 \\ 2 & 0 \end{pmatrix} & | ||
+ | \begin{pmatrix} 0 & 2 \\ 1 & 2 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 0 \\ 2 & 1 \end{pmatrix} \\ | ||
+ | \hline | ||
+ | a_0 & a_1 & a_2 & a_3 & a_4 \\ | ||
+ | \end{array} </tex> | ||
+ | |||
+ | Пусть <tex> G </tex> — операция умножения матриц. Дерево Фенвика <tex> t </tex> выглядит так: | ||
+ | |||
+ | <tex> \begin{array}{c||c||c||c||c} \begin{pmatrix} 1 & 0 \\ 0 & 2 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 2 \\ 0 & 2 \end{pmatrix} & | ||
+ | \begin{pmatrix} 0 & 1 \\ 2 & 0 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 10 \\ 0 & 8 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 0 \\ 2 & 1 \end{pmatrix} \\ | ||
+ | \hline | ||
+ | t_0 = a_0 & t_1 = a_0 \cdot a_1 & t_2 = a_2 & t_3 = a_0 \cdot a_1 \cdot a_2 \cdot a_3 & t_4 = a_4 \\ | ||
+ | \end{array} </tex> | ||
+ | |||
+ | Пусть теперь <tex> a_2' = a_2 \cdot d = \begin{pmatrix} 0 & 1 \\ 2 & 0 \end{pmatrix} \cdot \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} </tex>. Значит, надо изменить <tex> t_2 </tex> и <tex> t_{2 | (2 + 1)} = t_3 </tex>. | ||
+ | |||
+ | <tex> t_2' = t_2 \cdot s_{2, 2}^{-1} \cdot d \cdot s_{2, 2} = t_2 \cdot (s_2^{-1} \cdot s_2)^{-1} \cdot d \cdot (t_2^{-1} \cdot t_2) = t_2 \cdot d = a_2' </tex> | ||
+ | |||
+ | После этого дерево выглядит так: | ||
+ | |||
+ | <tex> \begin{array}{c||c||c||c||c} \begin{pmatrix} 1 & 0 \\ 0 & 2 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 2 \\ 0 & 2 \end{pmatrix} & | ||
+ | \begin{pmatrix} 3 & 4 \\ 2 & 4 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 10 \\ 0 & 8 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 0 \\ 2 & 1 \end{pmatrix} \\ | ||
+ | \hline | ||
+ | t_0 = a_0 & t_1 = a_0 \cdot a_1 & t_2' = a_2' & t_3 = a_0 \cdot a_1 \cdot a_2 \cdot a_3 & t_4 = a_4 \\ | ||
+ | \end{array} </tex> | ||
+ | |||
+ | Пересчитаем <tex> t_3' </tex>: | ||
+ | |||
+ | <tex> t_3' = t_3 \cdot s_{2, 3}^{-1} \cdot d \cdot s_{2, 3} </tex> | ||
+ | |||
+ | Рассчитаем суммы: | ||
+ | |||
+ | <tex> s_2' = t_{(2 \& 3) - 1} \cdot t_2' = t_1 \cdot t_2' = \begin{pmatrix} 1 & 2 \\ 0 & 2 \end{pmatrix} \cdot \begin{pmatrix} 3 & 4 \\ 2 & 4 \end{pmatrix} = \begin{pmatrix} 7 & 12 \\ 4 & 8 \end{pmatrix} </tex> | ||
+ | |||
+ | <tex> s_3 = t_3 = \begin{pmatrix} 1 & 10 \\ 0 & 8 \end{pmatrix} </tex> | ||
+ | |||
+ | <tex> s_{2, 3} = s_2'^{-1} \cdot s_3 = \begin{pmatrix} 1 & -2 \\ -0.5 & 2 \end{pmatrix} </tex> | ||
+ | |||
+ | <tex> t_3' = \begin{pmatrix} 12 & 38 \\ 8 & 24 \end{pmatrix} = a_0 \cdot a_1 \cdot a_2' \cdot a_3 </tex> | ||
+ | |||
+ | Итого в обновлённом дереве Фенвика всё верно: | ||
+ | |||
+ | <tex> \begin{array}{c||c||c||c||c} \begin{pmatrix} 1 & 0 \\ 0 & 2 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 2 \\ 0 & 2 \end{pmatrix} & | ||
+ | \begin{pmatrix} 3 & 4 \\ 2 & 4 \end{pmatrix} & | ||
+ | \begin{pmatrix} 12 & 38 \\ 8 & 24 \end{pmatrix} & | ||
+ | \begin{pmatrix} 1 & 0 \\ 2 & 1 \end{pmatrix} \\ | ||
+ | \hline | ||
+ | t_0 = a_0 & t_1 = a_0 \cdot a_1 & t_2' = a_2' & t_3' = a_0 \cdot a_1 \cdot a_2' \cdot a_3 & t_4 = a_4 \\ | ||
+ | \end{array} </tex> | ||
+ | ==См. также== | ||
+ | * [[Дерево Фенвика]] | ||
+ | * [[Дерево отрезков. Построение]] | ||
+ | |||
+ | ==Источники информации== | ||
+ | |||
+ | * [http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=F180153B9C0CD797594314B736E2CCC5?doi=10.1.1.14.8917&rep=rep1&type=pdf Peter M. Fenwick: A new data structure for cumulative frequency] | ||
+ | * [http://en.wikipedia.org/wiki/Fenwick_tree Wikipedia — Fenwick tree] | ||
+ | |||
+ | [[Категория: Дискретная математика и алгоритмы]] | ||
+ | [[Категория: Дерево Фенвика]] | ||
+ | [[Категория: Структуры данных]] |
Текущая версия на 19:23, 4 сентября 2022
Обычное дерево Фенвика позволяет выполнять некоторую ассоциативную, коммутативную, обратимую операцию на отрезке с изменением элементов. Описываемая модификация дает возможность отказаться от коммутативности .
Обновление элемента
Как и ранее, для обновления элемента в дереве нужно изменить все, что хранит результат операции с этим элементом. Но теперь нельзя просто применить операцию
(далее будем использовать мультипликативную нотацию) ко всем нужным элементам дерева. Пусть мы хотим изменить на , в данный момент обновляем элемент дерева с индексом . Вместо мы получим (так как больше нельзя переставлять элементы местами в операции на отрезке, ответ будет неверен).Для решения этой задачи нужно удалить отрезок после изменяемого элемента, изменить элемент, после чего добавить этот отрезок снова.
Теорема: |
Пусть — результат выполнения операции на префиксе ; — результат ее выполнения на отрезке . Тогда элемент дерева с индексом обновляется как . |
Доказательство: |
Может показаться, что этот способ не работает, так как , возможно, уже было изменено, а — еще нет, значит, мы удаляем не тот отрезок, который должны удалить. Убедимся, что на самом деле все обновляется правильно. Учитывая, что , получаем:; , то есть элемент дерева изменяется на правильное значение. |
Время работы
Пусть в дереве
элементов. Так как для каждого из изменяемых элементов дерева мы совершаем дополнительно запрос суммы на отрезке(а он работает за операций), то асимптотическое время работы обновления элемента ухудшается до .Пример
Пусть есть массив из пяти матриц
:
Пусть
— операция умножения матриц. Дерево Фенвика выглядит так:
Пусть теперь
. Значит, надо изменить и .
После этого дерево выглядит так:
Пересчитаем
:
Рассчитаем суммы:
Итого в обновлённом дереве Фенвика всё верно: