<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=178.70.63.225&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=178.70.63.225&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/178.70.63.225"/>
		<updated>2026-04-04T15:05:02Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%A4%D0%B5%D0%BD%D0%B2%D0%B8%D0%BA%D0%B0&amp;diff=75096</id>
		<title>Дерево Фенвика</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE_%D0%A4%D0%B5%D0%BD%D0%B2%D0%B8%D0%BA%D0%B0&amp;diff=75096"/>
				<updated>2020-10-20T17:59:13Z</updated>
		
		<summary type="html">&lt;p&gt;178.70.63.225: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание структуры ==&lt;br /&gt;
[[Файл:Bit.jpg|thumb|300px|По горизонтали — индексы массива &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; &amp;lt;br/&amp;gt; (&amp;lt;tex&amp;gt;T_i&amp;lt;/tex&amp;gt; является суммой элементов массива &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;, индексы которых заштрихованы),&amp;lt;br/&amp;gt; по вертикали — индексы массива &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;]]&lt;br /&gt;
'''Дерево Фе&amp;amp;#769;нвика''' (англ. ''Binary indexed tree'') — структура данных, требующая &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; памяти и позволяющая эффективно (за &amp;lt;tex&amp;gt; O(\log n) &amp;lt;/tex&amp;gt;) выполнять следующие операции:&lt;br /&gt;
* изменять значение любого элемента в массиве,&lt;br /&gt;
* выполнять некоторую [[Ассоциативная_операция |ассоциативную]], [[Абелева_группа |коммутативную]], [[Группа |обратимую операцию]] &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; на отрезке &amp;lt;tex&amp;gt; [i, j] &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Впервые описано Питером Фенвиком в 1994 году.&lt;br /&gt;
&lt;br /&gt;
Пусть дан массив &amp;lt;tex&amp;gt; A = [a_0, a_1, ... , a_{n - 1}]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Деревом Фенвика будем называть массив &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; элементов: &amp;lt;tex&amp;gt; T_i = \sum\limits_{k = F(i)}^{i} a_k&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; i = 0 .. n - 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; F(i) &amp;lt;/tex&amp;gt; — некоторая функция, от выбора которой зависит время работы операций над деревом. Рассмотрим функцию, позволяющую делать операции вставки и изменения элемента за время &amp;lt;tex&amp;gt; O(\log n) &amp;lt;/tex&amp;gt;. Она задается простой формулой: &amp;lt;tex&amp;gt; F(i) = i \And (i + 1) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \And &amp;lt;/tex&amp;gt; — это операция побитового логического &amp;lt;tex&amp;gt;AND&amp;lt;/tex&amp;gt;. При &amp;lt;tex&amp;gt;AND&amp;lt;/tex&amp;gt; числа и его значения, увеличенного на единицу, мы получаем это число без последних подряд идущих единиц.&lt;br /&gt;
&lt;br /&gt;
Эту функцию можно вычислять по другой формуле: &amp;lt;tex&amp;gt; F(i) = i - 2^{h(i)} + 1, &amp;lt;/tex&amp;gt; где &amp;lt;tex&amp;gt; h(i) &amp;lt;/tex&amp;gt; — количество подряд идущих единиц в конце бинарной записи числа &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;. Оба варианта равносильны, так как функция, заданная какой-либо из этих формул, заменяет все подряд идущие единицы в конце числа на нули.&lt;br /&gt;
&lt;br /&gt;
== Запрос изменения элемента ==&lt;br /&gt;
Нам надо научиться быстро изменять частичные суммы в зависимости от того, как изменяются элементы. Рассмотрим как изменяется массив &amp;lt;tex&amp;gt;T&amp;lt;/tex&amp;gt; при изменении элемента &amp;lt;tex&amp;gt;a_k&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement=&lt;br /&gt;
Для пересчёта дерева Фенвика при изменении величины &amp;lt;tex&amp;gt;a_{k}&amp;lt;/tex&amp;gt; необходимо изменить элементы дерева &amp;lt;tex&amp;gt;T_{i}&amp;lt;/tex&amp;gt;, для индексов &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; которых верно неравенство &amp;lt;tex&amp;gt;F(i) \leqslant k \leqslant i&amp;lt;/tex&amp;gt; .&lt;br /&gt;
|proof=&lt;br /&gt;
&amp;lt;tex&amp;gt; T_i =\sum\limits_{k = F(i)}^{i} a_k , i = 0 .. n - 1 \Rightarrow&amp;lt;/tex&amp;gt; необходимо менять те &amp;lt;tex&amp;gt;T_i&amp;lt;/tex&amp;gt;, для которых &amp;lt;tex&amp;gt;a_{k}&amp;lt;/tex&amp;gt; попадает в &amp;lt;tex&amp;gt;T_i \Rightarrow&amp;lt;/tex&amp;gt; необходимые &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; удовлетворяют условию &amp;lt;tex&amp;gt;F(i) \leqslant k \leqslant i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Лемма&lt;br /&gt;
|statement= Все такие &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;, для которых меняется &amp;lt;tex&amp;gt;T_i&amp;lt;/tex&amp;gt; при изменении &amp;lt;tex&amp;gt;a_k&amp;lt;/tex&amp;gt;, можно найти по формуле &amp;lt;tex&amp;gt;i_{next} = i_{prev}  \mid  (i_{prev} + 1) &amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; \mid &amp;lt;/tex&amp;gt; — это операция побитового логического &amp;lt;tex&amp;gt; OR &amp;lt;/tex&amp;gt;.&lt;br /&gt;
|proof=Из доказанной выше леммы следует, что первый элемент последовательности само &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;. Для него выполняется равенство, так как &amp;lt;tex&amp;gt; F(i) \leqslant i &amp;lt;/tex&amp;gt;. По формуле &amp;lt;tex&amp;gt;i_{next} = i_{prev}  \mid  (i_{prev} + 1) &amp;lt;/tex&amp;gt; мы заменим первый ноль на единицу. Неравенство при этом сохранится, так как &amp;lt;tex&amp;gt;F(i)&amp;lt;/tex&amp;gt; осталось прежним или уменьшилось, а &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; увеличилось. &amp;lt;tex&amp;gt; F(i) &amp;lt;/tex&amp;gt; не может увеличиться, так как функция &amp;lt;tex&amp;gt; F &amp;lt;/tex&amp;gt; заменяет последние подряд идущие единицы числа &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; на нули, а по формуле &amp;lt;tex&amp;gt;i_{next} = i_{prev}  \mid  (i_{prev} + 1) &amp;lt;/tex&amp;gt; у нового значения &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt; увеличивается количество единиц в конце, что не может привести к увеличению &amp;lt;tex&amp;gt; F(i) &amp;lt;/tex&amp;gt;. Докажем от противного, что нельзя рассматривать значения &amp;lt;tex&amp;gt; i &amp;lt;/tex&amp;gt;, отличные от тех, которые мы получили по формуле. Рассмотрим две различные последовательности индексов. Первая последовательность получена по формуле, вторая — некоторая последовательность чисел превосходящих &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;. Возьмём число &amp;lt;tex&amp;gt; j &amp;lt;/tex&amp;gt; из второй последовательности, которого нет в первой последовательности. Пусть &amp;lt;tex&amp;gt;F(j) \leqslant k &amp;lt;/tex&amp;gt;. Уберём у &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; все подряд идущие единицы в конце двоичной записи, столько же цифр уберём в конце числа &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;. Обозначим их как &amp;lt;tex&amp;gt;j_{0}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;k_{0}&amp;lt;/tex&amp;gt;. Чтобы выполнялось условие &amp;lt;tex&amp;gt;F(j)  \leqslant k &amp;lt;/tex&amp;gt;, должно выполняться неравенство &amp;lt;tex&amp;gt;j_{0} \leqslant k_{0}&amp;lt;/tex&amp;gt;. Но если &amp;lt;tex&amp;gt;j_{0} &amp;lt; k_{0}&amp;lt;/tex&amp;gt;, то и &amp;lt;tex&amp;gt;j \leqslant k&amp;lt;/tex&amp;gt;, что противоречит условию &amp;lt;tex&amp;gt;j &amp;gt; k&amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt;j_{0} = k_{0}&amp;lt;/tex&amp;gt;. Но тогда &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; возможно получить по формуле &amp;lt;tex&amp;gt;i_{next} = i_{prev}  \mid  (i_{prev} + 1) &amp;lt;/tex&amp;gt;, следовательно, &amp;lt;tex&amp;gt;F(j) &amp;gt; k &amp;lt;/tex&amp;gt;. Получили противоречие: &amp;lt;tex&amp;gt;j&amp;lt;/tex&amp;gt; можно вычислить по формуле, а это значит, что оно содержится в первой последовательности. Таким образом, нужные элементы можно искать по формуле &amp;lt;tex&amp;gt;i_{next} = i_{prev}  \mid  (i_{prev} + 1) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Заметим, что &amp;lt;tex&amp;gt;F(i)&amp;lt;/tex&amp;gt; возрастает немонотонно. Поэтому нельзя просто перебирать значения от &amp;lt;tex&amp;gt; k &amp;lt;/tex&amp;gt;, пока не нарушается условие. Например, пусть &amp;lt;tex&amp;gt; k = 3 &amp;lt;/tex&amp;gt;. При данной стратегии на следующем шаге (&amp;lt;tex&amp;gt; i = 4&amp;lt;/tex&amp;gt;) нарушится условие и мы прекратим пересчитывать &amp;lt;tex&amp;gt; T_i &amp;lt;/tex&amp;gt;. Но тогда мы упускаем остальные значения &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, например &amp;lt;tex&amp;gt; 7 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, десятичная запись&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;5&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;7&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;9&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, двоичная запись&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0000&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0001&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0010&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0011&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0100&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0101&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0110&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0111&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;1000&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;1001&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;1010&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;F(i)&amp;lt;/tex&amp;gt;, двоичная запись&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0000&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0000&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0010&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0000&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0100&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0100&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0110&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0000&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;1000&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;1000&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;1010&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;F(i)&amp;lt;/tex&amp;gt;, десятичная запись&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;6&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:3px 10px&amp;quot;| &amp;lt;tex&amp;gt;10&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Все &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; мы можем получить следующим образом: &amp;lt;tex&amp;gt;i_{next} = i_{prev}  \mid  (i_{prev} + 1) &amp;lt;/tex&amp;gt;. Следующим элементом в последовательности будет элемент, у которого первый с конца ноль превратится в единицу. Можно заметить, что если к исходному элементу прибавить единицу, то необходимый ноль обратится в единицу, но при этом все следующие единицы обнулятся. Чтобы обратно их превратить в единицы, применим операцию &amp;lt;tex&amp;gt;OR&amp;lt;/tex&amp;gt;. Таким образом все нули в конце превратятся в единицы и мы получим нужный элемент. Для того, чтобы понять, что эта последовательность верна, достаточно посмотреть на таблицу.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px&amp;quot;&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;i_{prev}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\ldots 011 \ldots 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;i_{prev} + 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\ldots 100 \ldots 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#EEE;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;i_{next}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 30px&amp;quot;| &amp;lt;tex&amp;gt;\ldots 111 \ldots 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Несложно заметить, что данная последовательность строго возрастает и в худшем случае будет применена логарифм раз, так как добавляет каждый раз по одной единице в двоичном разложении числа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Напишем функцию, которая будет прибавлять к элементу &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; число &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;, и при этом меняет соответствующие частичные суммы. Так как наш массив содержит &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt; элементов, то мы будем искать &amp;lt;tex&amp;gt;i_{next}&amp;lt;/tex&amp;gt; до тех пор, пока оно не превышает значение &amp;lt;tex&amp;gt;N&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''function''' modify(i, d):&lt;br /&gt;
    '''while''' i &amp;lt; N&lt;br /&gt;
        t[i] += d&lt;br /&gt;
        i = i | (i + 1)&lt;br /&gt;
&lt;br /&gt;
Часто можно встретить задачу, где требуется заменить значение элемента &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt; на &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Заметим, что если вычислить разность &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;a_{i}&amp;lt;/tex&amp;gt;, то можно свести эту задачу к операции прибавления &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; к &amp;lt;tex&amp;gt;a_i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''function''' set(i, x):&lt;br /&gt;
    d = x - a[i]&lt;br /&gt;
    a[i] = x&lt;br /&gt;
    modify(i, d)&lt;br /&gt;
&lt;br /&gt;
Построение дерева можно осуществить, исходя из его описания. Но можно быстрее, если использовать функцию &amp;lt;tex&amp;gt;\mathrm {modify}&amp;lt;/tex&amp;gt; для каждого элемента массива &amp;lt;tex&amp;gt;A&amp;lt;/tex&amp;gt;. Тогда мы получим время работы &amp;lt;tex&amp;gt;O(n \log {n})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''function''' build():&lt;br /&gt;
    '''for''' i = 0 '''to''' N - 1&lt;br /&gt;
        modify(i, a[i])&lt;br /&gt;
&lt;br /&gt;
== Запрос получения значения функции на префиксе ==&lt;br /&gt;
Пусть существует некоторая бинарная операция &amp;lt;tex&amp;gt;\circ&amp;lt;/tex&amp;gt;. Чтобы получить значение на отрезке &amp;lt;tex&amp;gt;[i, j]&amp;lt;/tex&amp;gt;, нужно провести операцию, обратную к &amp;lt;tex&amp;gt;\circ&amp;lt;/tex&amp;gt;, над значениями на отрезках &amp;lt;tex&amp;gt;[0, j]&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[0, i - 1]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве бинарной операции &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; рассмотрим операцию сложения.&lt;br /&gt;
&lt;br /&gt;
Обозначим &amp;lt;tex&amp;gt; G_i = \mathrm {sum(i)} = \sum\limits_{k = 0}^{i} a_k &amp;lt;/tex&amp;gt;. Тогда &amp;lt;tex&amp;gt; \mathrm {sum(i, j)} = \sum\limits_{k = i}^{j} a_k = G_j - G_{i - 1} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для нахождения &amp;lt;tex&amp;gt;\mathrm {sum(i)}&amp;lt;/tex&amp;gt; будем действовать следующим образом. Берём &amp;lt;tex&amp;gt;T_i&amp;lt;/tex&amp;gt;, которое является суммой элементов с индексами от &amp;lt;tex&amp;gt;F(i)&amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Теперь к этому значению нужно прибавить &amp;lt;tex&amp;gt;\mathrm {sum(F(i) - 1)}&amp;lt;/tex&amp;gt;. Аналогично продолжаем складывать, пока не &amp;lt;tex&amp;gt;F(i)&amp;lt;/tex&amp;gt; не станет равным &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Покажем, что запрос суммы работает за &amp;lt;tex&amp;gt;O(\log{n})&amp;lt;/tex&amp;gt;. Рассмотрим двоичную запись числа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;. Функция &amp;lt;tex&amp;gt;F(i)&amp;lt;/tex&amp;gt; заменила его последние единицы на нули (заметим, что количество нулей в конце станет больше, чем количество единиц в конце до этого). Теперь вычтем единицу из &amp;lt;tex&amp;gt;F(i)&amp;lt;/tex&amp;gt; (переход к следующему столбику). Количество единиц в конце увеличилось, по сравнению с &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, так как мы заменили все нули в конце на единицы. Проводя эти действия дальше, мы придём к тому, что получили &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;. В худшем случае мы должны были повторять эти операции &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; раз, где &amp;lt;tex&amp;gt;l&amp;lt;/tex&amp;gt; — количество цифр в двоичной записи числа &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt;, что не превосходит &amp;lt;tex&amp;gt;\log_{2}{i} + 1&amp;lt;/tex&amp;gt;. Значит, запрос суммы выполняется за &amp;lt;tex&amp;gt;O(\log{n})&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
Приведем код функции &amp;lt;tex&amp;gt; \mathrm {sum(i)} &amp;lt;/tex&amp;gt;:&lt;br /&gt;
 '''int''' sum(i):&lt;br /&gt;
    result = 0&lt;br /&gt;
    '''while''' i &amp;gt;= 0&lt;br /&gt;
        result += t[i]&lt;br /&gt;
        i = f(i) - 1&lt;br /&gt;
    return result&lt;br /&gt;
&lt;br /&gt;
==Сравнение дерева Фенвика и дерева отрезков==&lt;br /&gt;
&lt;br /&gt;
* Дерево Фенвика занимает в константное значение раз меньше памяти, чем дерево отрезков. Это следует из того, что дерево Фенвика хранит только значение операции для каких-то элементов, а дерево отрезков хранит сами элементы и частичные результаты операции на подотрезках, поэтому оно занимает как минимум в два раза больше памяти.&lt;br /&gt;
* Дерево Фенвика проще в реализации.&lt;br /&gt;
* Операция на отрезке, для которой строится дерево Фенвика, должна быть обратимой, а это значит, что минимум (как и максимум) на отрезке это дерево считать не может, в отличие от дерева отрезков. Но если нам требуется найти минимум на префиксе, то дерево Фенвика справится с этой задачей. Такое дерево Фенвика поддерживает операцию уменьшения элементов массива. Пересчёт минимума в дереве происходит быстрее, чем обновление массива минимумов на префиксе.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Дерево отрезков. Построение |Дерево отрезков]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
&lt;br /&gt;
* [http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=F180153B9C0CD797594314B736E2CCC5?doi=10.1.1.14.8917&amp;amp;rep=rep1&amp;amp;type=pdf Peter M. Fenwick: A new data structure for cumulative frequency]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Fenwick_tree Wikipedia — Fenwick tree]&lt;br /&gt;
* [http://e-maxx.ru/algo/fenwick_tree Maximal:: algo:: Дерево Фенвика]&lt;br /&gt;
* [http://habrahabr.ru/post/112828 Хабрахабр — Дерево Фенвика]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дерево Фенвика]]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Структуры данных]]&lt;/div&gt;</summary>
		<author><name>178.70.63.225</name></author>	</entry>

	</feed>