Дерево Фенвика для некоммутативных операций — различия между версиями
м (→Обновление элемента) |
|||
Строка 3: | Строка 3: | ||
== Обновление элемента == | == Обновление элемента == | ||
− | Как и ранее, для обновления элемента в дереве нужно изменить все, что хранит результат операции с этим элементом. Но теперь нельзя просто применить операцию <tex> G </tex> (далее используется мультипликативная нотация) ко всем нужным элементам дерева. Пусть мы хотим изменить <tex> a_i </tex> на <tex> a_i' = a_i \ | + | Как и ранее, для обновления элемента в дереве нужно изменить все, что хранит результат операции с этим элементом. Но теперь нельзя просто применить операцию <tex> G </tex> (далее используется мультипликативная нотация) ко всем нужным элементам дерева. Пусть мы хотим изменить <tex> a_i </tex> на <tex> a_i' = a_i \circ d </tex>, в данный момент обновляем элемент дерева с индексом <tex> j </tex>. Вместо <tex> a_{j\&(j+1)} \circ \ldots a_i'\circ \ldots \circ a_j </tex> мы получим <tex> a_{j\&(j+1)} \circ \ldots a_i \circ \ldots \circ a_j \circ a_i' </tex> (так как больше нельзя переставлять элементы местами в операции на отрезке, ответ будет неверен). |
− | Решение — нужно удалить отрезок после изменяемого элемента, изменить элемент, после чего добавить этот отрезок снова. Пусть <tex> s_i = a_1 \ | + | Решение — нужно удалить отрезок после изменяемого элемента, изменить элемент, после чего добавить этот отрезок снова. Пусть <tex> s_i = a_1 \circ a_2 \circ \ldots \circ a_i </tex> — результат выполнения операции на префиксе <tex> i </tex>, <tex> s_{i, j} = s_i^{-1} \circ s_j </tex> — результат ее выполнения на отрезке <tex> [i; j] </tex>. Тогда элемент дерева с индексом <tex> j </tex> обновляется как <tex> f_j \leftarrow f_j \circ s_{i, j}^{-1} \circ d \circ s_{i, j} </tex>. |
Может показаться, что этот способ не работает, так как <tex> s_i </tex>, возможно, уже было изменено, а <tex> s_j </tex> — еще нет, значит, мы удаляем не тот отрезок, который должны удалить. Убедимся, что на самом деле все обновляется правильно: | Может показаться, что этот способ не работает, так как <tex> s_i </tex>, возможно, уже было изменено, а <tex> s_j </tex> — еще нет, значит, мы удаляем не тот отрезок, который должны удалить. Убедимся, что на самом деле все обновляется правильно: | ||
− | <tex> s_{i, j}{'} = (s_i \ | + | <tex> s_{i, j}{'} = (s_i \circ d)^{-1} \circ s_j = d^{-1} \circ s_i^{-1} \circ s_j = d^{-1} \circ s_{i, j} </tex>; |
− | <tex> s_{i, j}^{-1}{'} \ | + | <tex> s_{i, j}^{-1}{'} \circ d \circ s_{i, j}{'} = (d^{-1} \circ s_{i, j})^{-1} \circ d \circ d^{-1} \circ s_{i, j} = s_{i, j}^{-1} \circ d \circ d \circ d^{-1} \circ s_{i, j} = s_{i, j}^{-1} \circ d \circ s_{i, j} </tex>, то есть элемент дерева изменяется на правильное значение. |
Пусть в дереве <tex> n </tex> элементов. Так как для каждого из <tex> O(\log(n)) </tex> изменяемых элементов дерева мы совершаем дополнительно запрос суммы на отрезке(а он работает за <tex> O(\log(n)) </tex> операций), то асимптотическое время работы обновления элемента ухудшается до <tex> O(\log^2(n)) </tex>. | Пусть в дереве <tex> n </tex> элементов. Так как для каждого из <tex> O(\log(n)) </tex> изменяемых элементов дерева мы совершаем дополнительно запрос суммы на отрезке(а он работает за <tex> O(\log(n)) </tex> операций), то асимптотическое время работы обновления элемента ухудшается до <tex> O(\log^2(n)) </tex>. |
Версия 16:53, 11 июня 2012
Обычное дерево Фенвика позволяет выполнять некоторую ассоциативную, коммутативную, обратимую операцию на отрезке с изменением элементов. Описываемая модификация дает возможность отказаться от коммутативности .
Обновление элемента
Как и ранее, для обновления элемента в дереве нужно изменить все, что хранит результат операции с этим элементом. Но теперь нельзя просто применить операцию
(далее используется мультипликативная нотация) ко всем нужным элементам дерева. Пусть мы хотим изменить на , в данный момент обновляем элемент дерева с индексом . Вместо мы получим (так как больше нельзя переставлять элементы местами в операции на отрезке, ответ будет неверен).Решение — нужно удалить отрезок после изменяемого элемента, изменить элемент, после чего добавить этот отрезок снова. Пусть
— результат выполнения операции на префиксе , — результат ее выполнения на отрезке . Тогда элемент дерева с индексом обновляется как .Может показаться, что этот способ не работает, так как
, возможно, уже было изменено, а — еще нет, значит, мы удаляем не тот отрезок, который должны удалить. Убедимся, что на самом деле все обновляется правильно:;
, то есть элемент дерева изменяется на правильное значение.
Пусть в дереве
элементов. Так как для каждого из изменяемых элементов дерева мы совершаем дополнительно запрос суммы на отрезке(а он работает за операций), то асимптотическое время работы обновления элемента ухудшается до .Выполнение запроса
Выполнение запроса делается так же, как и в обычном дереве Фенвика, с той лишь разницей, что теперь важен порядок операндов в операции
.