<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Lelyte</title><author><name>Lelyte</name></author><id>https://teletype.in/atom/lelyte</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/lelyte?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@lelyte?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=lelyte"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/lelyte?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-17T07:57:05.915Z</updated><entry><id>lelyte:sqrt_opt</id><link rel="alternate" type="text/html" href="https://teletype.in/@lelyte/sqrt_opt?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=lelyte"></link><title>Корневые оптимизации</title><published>2022-09-16T16:20:10.703Z</published><updated>2022-09-16T16:20:10.703Z</updated><category term="179" label="179"></category><summary type="html">Рассмотрим такую задачу
Мы хотим делать две операции:
  1) a[l; r] += x
  2) a[l; r] &lt; x</summary><content type="html">
  &lt;section style=&quot;background-color:hsl(hsl(263, 48%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2 id=&quot;NpYE&quot;&gt;Корневая декомпозиция&lt;/h2&gt;
    &lt;p id=&quot;MjeK&quot;&gt;Рассмотрим такую задачу&lt;br /&gt;Мы хотим делать две операции:&lt;br /&gt;  1) a[l; r] += x&lt;br /&gt;  2) a[l; r] &amp;lt; x&lt;/p&gt;
    &lt;p id=&quot;K2rZ&quot;&gt;Решение:&lt;br /&gt;Разобьем наш массив на K блоков (спойлер. K = √n)&lt;br /&gt;Тогда наш отрезок запроса разобьется на неполные блоки (по краям), а так же на полные блоки&lt;/p&gt;
    &lt;p id=&quot;Rfoq&quot;&gt;Для каждого неполного блока сделаем операции в тупую за O(√n)&lt;/p&gt;
    &lt;p id=&quot;mqcr&quot;&gt;Теперь рассмотрим полные блок&lt;/p&gt;
    &lt;p id=&quot;caLH&quot;&gt;Для операции 1:&lt;br /&gt;Будем хранить в массиве buff[i] (где i - номер блока) - сколько мы добавили в блок i&lt;/p&gt;
    &lt;p id=&quot;BhsZ&quot;&gt;Для операции 2:&lt;/p&gt;
    &lt;p id=&quot;08nX&quot;&gt;Будем хранить отсортированные отрезки. Отвечать будем на запросы с помощью Бинарного поиска за O(LogN) для блока. То есть возьмем числа, для которых верно: a[i] + buff[num(i)] &amp;lt; x&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2 id=&quot;3CeG&quot;&gt;Алгоритм МО&lt;/h2&gt;
    &lt;p id=&quot;NRvq&quot;&gt;Рассмотрим такую задачу&lt;br /&gt;Дано много-много запросов, состоящий из границ отрезка и числа x&lt;br /&gt;Вам нужно для каждого отрезка ответить на вопрос: Сколько чисел, лежащий в нашем отрезке равны x?&lt;/p&gt;
    &lt;p id=&quot;5inS&quot;&gt;Решение:&lt;br /&gt;Воспользуемся Алгоритмом МО&lt;/p&gt;
    &lt;p id=&quot;XnAf&quot;&gt;Для начала, чтобы все работало намного быстрее, чем сейчас - сожмем числа&lt;br /&gt;То есть:&lt;br /&gt;Пусть есть массив [1, 5, 3, 6, 1, 6] -&amp;gt; [1, 2, 3, 4, 1, 4]&lt;/p&gt;
    &lt;p id=&quot;IIrp&quot;&gt;Воспользуемся идеей из прошлой задачи и разобьем отрезки в блоки по левой границе. Внутри блока отсортируем их по правой границе&lt;/p&gt;
    &lt;p id=&quot;aTpq&quot;&gt;Дальше, внутри каждого нового блока посчитаем ответ в тупую для первого отрезка&lt;/p&gt;
    &lt;p id=&quot;YBVf&quot;&gt;Дальше, для каждого блока будем двигать левые границы в тупую, а правую - только направо&lt;/p&gt;
    &lt;p id=&quot;1UWK&quot;&gt;Тогда суммарно наша правая граница пройдет максимум N элементов =&amp;gt; работает за O(N)&lt;/p&gt;
    &lt;p id=&quot;kQrb&quot;&gt;Всего блоков √n =&amp;gt; Суммарная асимптотика O(n√n) &lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(199, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2 id=&quot;WGhB&quot;&gt;Военная хитрость:&lt;/h2&gt;
    &lt;p id=&quot;4QfY&quot;&gt;Нечетные блоки отсортируем по возрастанию, четные - по убыванию (это будет работать быстрее)&lt;/p&gt;
    &lt;p id=&quot;wLUy&quot;&gt;лол&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h2 id=&quot;i5MX&quot;&gt;Оптимизация какого-то что?&lt;/h2&gt;
    &lt;p id=&quot;pxWz&quot;&gt;жесть там какие-то тяжелые и легкие вершины, но задача изи короче мне пофиг &lt;/p&gt;
  &lt;/section&gt;

</content></entry><entry><id>lelyte:strings</id><link rel="alternate" type="text/html" href="https://teletype.in/@lelyte/strings?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=lelyte"></link><title>Z-функция, Префикс-Функция, Бор, Манакер</title><published>2022-06-13T08:52:27.968Z</published><updated>2022-06-13T08:52:47.506Z</updated><category term="sirius-2022" label="Sirius 2022"></category><summary type="html">Z-функция - это длина максимального префикса подстроки S, который начинается в x, который одновременно является префиксом нашей строки S
s[x ... x + k] == s[0 ... k]</summary><content type="html">
  &lt;section style=&quot;background-color:hsl(hsl(263, 48%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;UXHR&quot;&gt;Z-функция&lt;/h3&gt;
    &lt;p id=&quot;lMgq&quot;&gt;Z-функция - это длина максимального префикса подстроки S, который начинается в x, который одновременно является префиксом нашей строки S&lt;br /&gt;s[x ... x + k] == s[0 ... k]&lt;/p&gt;
    &lt;p id=&quot;k6al&quot;&gt;Код:&lt;/p&gt;
    &lt;pre id=&quot;FV1g&quot;&gt;int n;
str s;
vector&amp;lt;int&amp;gt; z(n);
int l = 0, r = 0;
for(int i = 1; i &amp;lt; n; i++){
    if(i &amp;lt;= r){
        z[i] = min(z[i - l], r - i + 1);
    }
    while(z[i] + i &amp;lt; n &amp;amp;&amp;amp; s[z[i]] == s[z[i] + i]){
         z[i]++;
    }
    if(z[i] + i - 1 &amp;gt; r){
        l = i;
        r = z[i] + i - 1;
    }
}&lt;/pre&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(34,  84%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;Nxx2&quot;&gt;Префикс Функция&lt;/h3&gt;
    &lt;p id=&quot;HRyP&quot;&gt;Префикс функцией от строки S называется такой массив p, где Pi - это длина наибольшего префикса длинны S, который также является суффиксом i-того префикса (не считая весь i-й префикс)&lt;/p&gt;
    &lt;p id=&quot;8tI1&quot;&gt;Например, для строки &amp;quot;aataataa&amp;quot; префикс функция будет равна [0,1,0,1,2,3,4,5]&lt;/p&gt;
    &lt;p id=&quot;XGGS&quot;&gt;Код:&lt;/p&gt;
    &lt;pre id=&quot;ohWa&quot;&gt;int n;
str s;
vector&amp;lt;int&amp;gt; p(n);
for(int i = 1; i &amp;lt; n; i++){
    int tmp = p[i - 1]
    while(s[i] != s[tmp] &amp;amp;&amp;amp; tmp){
        tmp = s[tmp - 1]
    }
    if(s[i] == s[tmp]){
        p[i] = tmp + 1;
    }
}&lt;/pre&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;fRmC&quot;&gt;Манакер&lt;/h3&gt;
    &lt;p id=&quot;4My6&quot;&gt;Пусть у нас есть строка S и мы хотим в ней найти все подпалиндромы&lt;/p&gt;
    &lt;p id=&quot;MOxh&quot;&gt;&lt;a href=&quot;https://ru.algorithmica.org/cs/string-searching/manacher/&quot; target=&quot;_blank&quot;&gt;https://ru.algorithmica.org/cs/string-searching/manacher/&lt;/a&gt; - тут&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(323, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;nmmZ&quot;&gt;Бор&lt;/h3&gt;
    &lt;p id=&quot;Yekw&quot;&gt;Бор — это структура данных для компактного хранения строк&lt;/p&gt;
  &lt;/section&gt;

</content></entry><entry><id>lelyte:dp_2</id><link rel="alternate" type="text/html" href="https://teletype.in/@lelyte/dp_2?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=lelyte"></link><title>ДП по подмножествам, ДП по профилю</title><published>2022-06-11T07:46:53.377Z</published><updated>2022-06-11T07:46:53.377Z</updated><category term="sirius-2022" label="Sirius 2022"></category><summary type="html">dp[last][mask] = min длина Гамильтонова пути из S в Last, если посетить вершины mask
dp[last][mask] -&gt; dp[next][mask | (1 &lt;&lt; next)]
next не принадлежит mask
last-&gt;next есть в графе
𝒪(2^n * n^2)</summary><content type="html">
  &lt;h2 id=&quot;XxM6&quot; data-align=&quot;center&quot;&gt;ДП по подмножествам&lt;/h2&gt;
  &lt;section style=&quot;background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;ORiy&quot;&gt;Вопросы, на которые вы должны сами отвечать&lt;/h3&gt;
    &lt;ol id=&quot;D5Ku&quot;&gt;
      &lt;li id=&quot;PD55&quot;&gt;Что считаем?&lt;/li&gt;
      &lt;li id=&quot;mEHt&quot;&gt;Как считаем?&lt;/li&gt;
      &lt;li id=&quot;WBYQ&quot;&gt;В каком порядке считаем?&lt;/li&gt;
      &lt;li id=&quot;kIJ9&quot;&gt;Какие начальные значения?&lt;/li&gt;
      &lt;li id=&quot;2Uj9&quot;&gt;Где ответ?&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;QXSx&quot;&gt;Гамильтонов путь&lt;/h3&gt;
    &lt;p id=&quot;wUs5&quot;&gt;dp[last][mask] = min длина Гамильтонова пути из S в Last, если посетить вершины mask&lt;br /&gt;dp[last][mask] -&amp;gt; dp[next][mask | (1 &amp;lt;&amp;lt; next)]&lt;br /&gt;next не принадлежит mask&lt;br /&gt;last-&amp;gt;next есть в графе&lt;br /&gt;𝒪(2^n * n^2)&lt;/p&gt;
    &lt;p id=&quot;IXhz&quot;&gt;Начальные значения:&lt;br /&gt;dp[s][1 &amp;lt;&amp;lt; s] = 0, остальные - INF&lt;/p&gt;
    &lt;p id=&quot;SM7G&quot;&gt;Где ответ?&lt;br /&gt;dp[i][полная маска]&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(34,  84%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;iBQ8&quot;&gt;Кол-во гамильтоновых путей из вершины S&lt;/h3&gt;
    &lt;p id=&quot;Eydq&quot;&gt;dp[last][mask] = кол-во Гамильтоновых путей из S в last, если посетили вершины mask&lt;br /&gt;dp[last][mask] -&amp;gt; dp[next][mask | (1 &amp;lt;&amp;lt; next)]&lt;br /&gt;next не принадлежит mask&lt;br /&gt;last-&amp;gt;next есть в графе&lt;br /&gt;dp[s][1 &amp;lt;&amp;lt; s] = 1&lt;br /&gt;dp[next][mask | (1 &amp;lt;&amp;lt; next)] += dp[last][mask]&lt;/p&gt;
    &lt;p id=&quot;JUv9&quot;&gt;Ответ?&lt;br /&gt;SUM dp[i][(1 &amp;lt;&amp;lt; n) - 1]&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(199, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;tnL0&quot;&gt;Введите текст&lt;/h3&gt;
    &lt;p id=&quot;FBMW&quot;&gt;Есть числа 0...2^n - 1&lt;br /&gt;a[0], a[1], .. a[2^n - 1]&lt;br /&gt;Для каждой mask посчитать сумму:&lt;br /&gt;SUM a[i], где i - подмаска нашей маски&lt;/p&gt;
    &lt;p id=&quot;QJem&quot;&gt;Пример:&lt;br /&gt;mask = 6 = 100&lt;br /&gt;a[000] + a[010] + a[100] + a[110]&lt;/p&gt;
    &lt;pre id=&quot;Rg9x&quot;&gt;int n;
for(int mask = 0; mask &amp;lt; (1 &amp;lt;&amp;lt; n); mask++){
    for(int submask = mask; submask &amp;gt; 0; submask=(submask - 1)&amp;amp;mask){
        ...
    }
}&lt;/pre&gt;
    &lt;p id=&quot;izr6&quot;&gt;dp[mask][i] - сумма a[submask], где биты 0...I в mask и subtask могут различаться, а остальные совпадают &lt;/p&gt;
    &lt;p id=&quot;8gP8&quot;&gt;dp[mask][0] = a[mask]&lt;br /&gt;Если i-тый бит mask = 0, то dp[mask][i + 1] = dp[mask][i] &lt;br /&gt;Иначе dp[mask][i + 1] = dp[mask][i] + dp[mask ^ (1 &amp;lt;&amp;lt; i)][i] &lt;/p&gt;
    &lt;pre id=&quot;pf6M&quot;&gt;for(int i = 0; i &amp;lt; n; i++){
    for(int mask = 0; mask &amp;lt; (1 &amp;lt;&amp;lt; n); mask++){
        dp[mask][i + 1] = dp[mask][i]
        if((mask &amp;gt;&amp;gt; i) &amp;amp; 1){
            dp[mask][i + 1] += dp[mask ^ (1 &amp;lt;&amp;lt; i)][i]
        }
    }
}&lt;/pre&gt;
    &lt;p id=&quot;czkT&quot;&gt;Оптимизация: можно сделать dp - одномерным, тогда получим такой код:&lt;/p&gt;
    &lt;pre id=&quot;FSdy&quot;&gt;for(int i = 0; i &amp;lt; n; i++){
    for(int mask = 0; mask &amp;lt; (1 &amp;lt;&amp;lt; n); mask++){
        if((mask &amp;gt;&amp;gt; i) &amp;amp; 1){
            dp[mask] += dp[mask ^ (1 &amp;lt;&amp;lt; i)]
        }
    }
}&lt;/pre&gt;
    &lt;p id=&quot;UY27&quot;&gt;Работает столько же, но памяти намного меньше&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 id=&quot;4GQo&quot; data-align=&quot;center&quot;&gt;ДП по профилю&lt;/h2&gt;
  &lt;section style=&quot;background-color:hsl(hsl(55,  86%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;DfJ7&quot;&gt;пошли нафиг&lt;/h3&gt;
    &lt;p id=&quot;yeBY&quot;&gt;&lt;a href=&quot;https://wiki.algocode.ru/index.php?title=&quot; target=&quot;_blank&quot;&gt;https://wiki.algocode.ru/index.php?title=&lt;/a&gt;ДП_по_профилю&lt;/p&gt;
  &lt;/section&gt;

</content></entry><entry><id>lelyte:fenwick_and_sparcetable</id><link rel="alternate" type="text/html" href="https://teletype.in/@lelyte/fenwick_and_sparcetable?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=lelyte"></link><title>Дерево Фенвика + Sparse Table ~ Сириус 07.06</title><published>2022-06-07T07:53:01.593Z</published><updated>2022-06-07T11:37:22.580Z</updated><category term="sirius-2022" label="Sirius 2022"></category><summary type="html">Дерево Фенвика - структура данных, дерево на одномерном массиве, которая обладает такими свойствами, как:</summary><content type="html">
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;eONt&quot;&gt;Дерево Фенвика&lt;/h3&gt;
    &lt;p id=&quot;PwRO&quot;&gt;&lt;strong&gt;&lt;em&gt;Дерево Фенвика&lt;/em&gt;&lt;/strong&gt; - структура данных, дерево на одномерном массиве, которая обладает такими свойствами, как:&lt;/p&gt;
    &lt;ol id=&quot;Xn3C&quot;&gt;
      &lt;li id=&quot;wE7l&quot;&gt;Сумма на отрезке с L по R&lt;/li&gt;
      &lt;li id=&quot;Sugh&quot;&gt;Изменение значения в какой-то позиции за O(LogN)&lt;/li&gt;
      &lt;li id=&quot;ekYe&quot;&gt;Требует O(N) памяти&lt;/li&gt;
    &lt;/ol&gt;
    &lt;p id=&quot;4xfX&quot;&gt;Код:&lt;/p&gt;
    &lt;pre id=&quot;EkcP&quot;&gt;ll n;
vector&amp;lt;ll&amp;gt; sum;

ll get_sum(ll i){ //сумма
    ll ans = 0;
    for(; i &amp;gt;= 0; i = (i&amp;amp;(i+1))-1){
        ans += sum[i];
    }
    return ans;
}

void update(ll i, ll x){ //обновление на точке
    for(; i &amp;lt; n; i = (i | (i+1))){
        sum[i] += x;
    }
}

ll sum_otr(ll l, ll r){
    return get_sum(r) - get_sum(l-1);
}&lt;/pre&gt;
    &lt;p id=&quot;IhPn&quot;&gt;Так же можно сделать MAX на отрезке, но это извращение, проще написать ДО&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;BkvM&quot;&gt;Двумерное Дерево Фенвика&lt;/h3&gt;
    &lt;p id=&quot;lPO6&quot;&gt;Аналогично &lt;/p&gt;
    &lt;p id=&quot;xMQN&quot;&gt;Код (скорее всего с багами):&lt;/p&gt;
    &lt;pre id=&quot;IQXD&quot;&gt;ll n;
vector&amp;lt;vector&amp;lt;ll&amp;gt;&amp;gt; f(MAXN, vector&amp;lt;ll&amp;gt;(MAXN));


ll get_sum(int i, int j){
    int r = 0;
    while(j &amp;gt; 0){
        int k = i;
        while(k &amp;gt; 0){
            r += f[k][j];
            k -= k &amp;amp; -k;
        }
        j = j &amp;amp; -j;
    }
    return r;
}


ll sum(int x1, int y1, int x2, int y2){
    return get_sum(x2, y2) - get_sum(x1, y2) - get_sum(x2, y1) + get_sum(x1, y1);
}

void add(int i, int j, int x){
    while(j &amp;lt;= n){
        int k = i;
        while(k &amp;lt;= n){
            f[k][j] += x;
            k += k &amp;amp; (~k);
        }
        j += j &amp;amp; (~j);
    }
}&lt;/pre&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;jXIY&quot;&gt;Sparse Table&lt;/h3&gt;
    &lt;p id=&quot;MDZS&quot;&gt;Sparse Table - структура данных, позволяющая находить минимум на отрезке&lt;/p&gt;
    &lt;pre id=&quot;uEvE&quot;&gt;#define MAX 100010
#define LOGMAX 30

ll n;
vector &amp;lt;ll&amp;gt; arr;
vector &amp;lt;vector&amp;lt;ll&amp;gt;&amp;gt; Sparce(MAX, vector&amp;lt;ll&amp;gt;(LOGMAX));

ll task(ll l, ll r) {
    ll j = (ll) log2(r - l + 1);
    if (Sparce[l][j] &amp;lt;= Sparce[r - (1 &amp;lt;&amp;lt; j) + 1][j]) {
        return Sparce[l][j];
    }
    return Sparce[r - (1 &amp;lt;&amp;lt; j) + 1][j];
}

...
в функции main 
for (ll i = 0; i &amp;lt; n; i++) {
    Sparce[i][0] = arr[i];
}
for (ll j = 1; (1 &amp;lt;&amp;lt; j) &amp;lt;= n; j++) {
    for (ll i = 0; (i + (1 &amp;lt;&amp;lt; j) - 1) &amp;lt; n; i++) {
        if (Sparce[i][j - 1] &amp;lt; Sparce[i + (1 &amp;lt;&amp;lt; (j - 1))][j - 1]) {
            Sparce[i][j] = Sparce[i][j - 1];
        } else {
            Sparce[i][j] = Sparce[i + (1 &amp;lt;&amp;lt; (j - 1))][j - 1];
        }
    }
}&lt;/pre&gt;
    &lt;p id=&quot;WcKv&quot;&gt;Оптимизация:&lt;/p&gt;
    &lt;pre id=&quot;PQv7&quot;&gt;#define MAX 100010
#define LOGMAX 30
ll n;
vector &amp;lt;ll&amp;gt; arr;
vector &amp;lt;vector&amp;lt;ll&amp;gt;&amp;gt; Sparce(LOGMAX, vector&amp;lt;ll&amp;gt;(MAX));

ll task(ll l, ll r) {
    ll j = (ll) log2(r - l);
    return min(Sparce[j][l], Sparce[j][r - (1 &amp;lt;&amp;lt; j)]);
}


int main() {
    for (ll i = 0; i &amp;lt; n; i++) {
        Sparce[0][i] = arr[i];
    }
    for (ll j = 0; j &amp;lt; LOGMAX - 1; j++) {
        for (ll i = 0; i + (2 &amp;lt;&amp;lt; j) &amp;lt;= n; i++) {
            Sparce[j + 1][i] = min(Sparce[j][i], Sparce[j][i + (1 &amp;lt;&amp;lt; j)]);
        }
    }
}
&lt;/pre&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;9taj&quot;&gt;Disjoint Sparse Table&lt;/h3&gt;
    &lt;p id=&quot;lOOr&quot;&gt;Sparse Table не мог быть построен для тех функций от подотрезка массива, для которых каждое число подотрезка должно быть учтено ровно один раз. Disjoint Sparse Table решает эту проблему и с предподсчётом за O(nlogn) позволяет в онлайне за O(1) находить почти любые функции от подотрезка, например кол-во минимумов, или произведение по непростому модулю. ~ wiki.algocode.ru&lt;/p&gt;
    &lt;p id=&quot;rmKt&quot;&gt;Основная идея: разделяй и властвуй&lt;br /&gt;&lt;br /&gt;TODO: написать дальше, автор конспекта закрыл ноут и пошел внимательно слушать&lt;br /&gt;&lt;br /&gt;Ссылки данной штуки: &lt;a href=&quot;https://algorithmica.org/ru/sparse-table&quot; target=&quot;_blank&quot;&gt;https://algorithmica.org/ru/sparse-table&lt;/a&gt;, &lt;a href=&quot;https://wiki.algocode.ru/index.php?title=Disjoint_Sparse_Table&quot; target=&quot;_blank&quot;&gt;https://wiki.algocode.ru/index.php?title=Disjoint_Sparse_Table&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;

</content></entry><entry><id>lelyte:number_theory</id><link rel="alternate" type="text/html" href="https://teletype.in/@lelyte/number_theory?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=lelyte"></link><title>Теория Чисел ~ Сириус 05.06</title><published>2022-06-05T07:27:56.838Z</published><updated>2022-06-05T09:22:01.497Z</updated><category term="sirius-2022" label="Sirius 2022"></category><summary type="html">Основная теорема арифметики гласит, что каждое число раскладывается на простые множители, причем единственным образом</summary><content type="html">
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;GNWx&quot;&gt;Основная теорема арифметики&lt;/h3&gt;
    &lt;p id=&quot;taqV&quot;&gt;Основная теорема арифметики гласит, что каждое число раскладывается на простые множители, причем единственным образом&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;GUdw&quot;&gt;Факторизация за O(sqrtN)&lt;/h3&gt;
    &lt;p id=&quot;NuRA&quot;&gt;Пусть у нас есть число N&lt;br /&gt;Оно представимо в виде N = a * b. Заметим, что одно из чисел a и b &amp;lt;= sqrt(n) (иначе a * b &amp;gt; n) =&amp;gt; можно перебирать делители N до его корны&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;WJWL&quot;&gt;Решето Эратосфена за O(NLogLogN)&lt;/h3&gt;
    &lt;pre id=&quot;deto&quot;&gt;//БУДЬТЕ АККУРАТНЕЙ С ПЕРЕПОЛНЕНИЕМ!!!
int n;
vector&amp;lt;bool&amp;gt; isPrime(n);
for(int i = 2; i &amp;lt;= n; i++){
    isPrime[i] = true;
}
for(int i = 2; i * i &amp;lt;= n; i++){
    if(isPrime[i]){
        for(int j = i * i; j &amp;lt;= n; j++){
            isPrime[j] = false;
        }
    }
} &lt;/pre&gt;
    &lt;h3 id=&quot;pMqN&quot;&gt;Прикол с minDiv (чтобы факторизацию делать)&lt;/h3&gt;
    &lt;pre id=&quot;raQK&quot;&gt;int n;
vector&amp;lt;int&amp;gt; minDiv(n);
vector&amp;lt;bool&amp;gt; isPrime(n);
for(int i = 2; i &amp;lt;= n; i++){
    isPrime[i] = true;
    minDiv[i] = i;
}
for(int i = 2; i * i &amp;lt;= n; i++){
    if(isPrime[i]){
        for(int j = i * i; j &amp;lt;= n; j++){
            isPrime[j] = false;
            minDiv[j] = min(minDiv[j], i);
        }
    }
}&lt;/pre&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;SOkD&quot;&gt;Диофантовы уравнения&lt;/h3&gt;
    &lt;p id=&quot;v5l0&quot;&gt;Уравнения вида a*x + b*y = c (a, b, c - известны)&lt;/p&gt;
    &lt;p id=&quot;SxQg&quot;&gt;Прикол:&lt;br /&gt;Если (a, b) = g, то существуют x и y такие, что a*x + b*y = g&lt;br /&gt;(a, b) -&amp;gt; (b, a % b) &lt;br /&gt;b * x1 + (a % b) * y1 = g&lt;br /&gt;(Для тех, кто не знал - a % b = a - [a / b] * b)&lt;br /&gt;b*x1 + (a - [a / b] * b) * y1 = a * y1 + b * (x1 - [a / b] * y1)&lt;br /&gt;Пример шапки функции:&lt;/p&gt;
    &lt;pre id=&quot;jo9k&quot;&gt;int gcd(int a, int b, int &amp;amp;x, int &amp;amp;y){
    ...
}&lt;/pre&gt;
    &lt;p id=&quot;n5EQ&quot;&gt;Заметим, что a * (x + b) + b (y - a) = a * x + b * y =&amp;gt; x = x0 + t * b/g; &lt;br /&gt;y = y0 - t * a/g&lt;br /&gt;&lt;br /&gt;Теперь решим основную задачу&lt;br /&gt;Воспользуемся тем, что мы умеем решать для НОДа и тупо домножим коэффициенты.&lt;br /&gt;Если c % g == 0 =&amp;gt; решений бесконечно много&lt;br /&gt;Если c % g != 0 =&amp;gt; решений нет&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;RzM6&quot;&gt;Функция Эйлера&lt;/h3&gt;
    &lt;p id=&quot;M6Qj&quot;&gt;ф(n) (да, это фи) - количество взаимнопростых чисел, которые меньше n&lt;br /&gt;ф(10) = 4&lt;/p&gt;
    &lt;p id=&quot;Vl4q&quot;&gt;Заметим тупые свойства:&lt;/p&gt;
    &lt;ol id=&quot;kMNy&quot;&gt;
      &lt;li id=&quot;MWhu&quot;&gt;ф(р) = р - 1&lt;/li&gt;
      &lt;li id=&quot;oPcY&quot;&gt;ф(р^n) = p^n - p^(n - 1)&lt;/li&gt;
    &lt;/ol&gt;
    &lt;p id=&quot;vCCq&quot;&gt;Так же интересное свойство:&lt;br /&gt;ф(a) * ф(b) = ф(a*b) для (a, b) = 1 (я не собираюсь это доказывать, так как а) это никому не нужно, б) это долго и скучно)&lt;br /&gt;&lt;br /&gt;Тогда достаточно просто считается ф(n) для любого n&lt;br /&gt;ф(n) = ф(p1^L1 * p2^L2 * p3^L3 * ... ) = ф(p1^L1) * ф(p2^L2) * ... = (тупое свойство 2) = n * (p1 - 1 / p1) * ...  * (pK - 1 / pK)&lt;br /&gt;(лучше считать через ans / p, ans *= (p - 1)&lt;br /&gt;&lt;/p&gt;
    &lt;pre id=&quot;q3QH&quot;&gt;int n;
int ans = n;
for(int i = 2; i * i &amp;lt;= n; i++){
    if(n % i == 0){
        ans /= i;
        ans *= (i - 1);
        while(n % i == 0){
            n /= i;
        }
    }
}
if(n &amp;gt; 1){
    ans /= n;
    ans *= (n - 1);
}&lt;/pre&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;Y9oD&quot;&gt;Количество делителей числа&lt;/h3&gt;
    &lt;p id=&quot;ZN7n&quot;&gt;Пусть у нас n = p1^L1 + p2^L2 + p3^L3 + ... + pK^LK&lt;br /&gt;Тогда, кол-во делителей = (L1 + 1) * (L2 + 2) * (L3 + 3) * ... * (LK + 1) (очевидно)&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;KZ72&quot;&gt;Малая Теорема Ферма&lt;/h3&gt;
    &lt;p id=&quot;6R1B&quot;&gt;a^(p - 1) ≡ 1 (mod p) при (a, p) = 1&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;J6Tq&quot;&gt;Теорема Эйлера&lt;/h3&gt;
    &lt;p id=&quot;KUSa&quot;&gt;a^ф(n) ≡ 1 (mod m) при (a, m) = 1&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;1utd&quot;&gt;Функции модульной арифметики&lt;/h3&gt;
    &lt;pre id=&quot;MdqI&quot;&gt;const int MOD = 998244353;


int add(int a, int b){
    if(a + b &amp;gt;= MOD){
        return a + b - MOD;
    }
    else{
        return a + b;
    }
}


int sub(int a, int b){
    if(a - b &amp;lt; 0){
        return a + b - MOD;
    }
    else{
        return a - b;
    }
}
&lt;/pre&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;EP6g&quot;&gt;Китайская теорема об остатках&lt;/h3&gt;
    &lt;p id=&quot;D2na&quot;&gt;TODO (сори, я не успел записать)&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;ys88&quot;&gt;Мем с модулями&lt;/h3&gt;
    &lt;p id=&quot;1ESJ&quot;&gt;a * g ≡ b * g (mod m * g) -&amp;gt; a ≡ b (mod m)&lt;br /&gt;a * g ≡ b * g (mod m) -&amp;gt; a ≡ b (mod m) при (m, g) = 1&lt;br /&gt;a ≡ b (mod m) -&amp;gt; a + x ≡ b + x (mod m)&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;g4cK&quot;&gt;С из N по K&lt;/h3&gt;
    &lt;p id=&quot;vDdt&quot;&gt;(n, k) = n! / (k! * (n - k)!)&lt;br /&gt;n! = (n - 1)! * n&lt;/p&gt;
    &lt;p id=&quot;fvpe&quot;&gt;надеюсь я с комментариями нигде не напутал...&lt;/p&gt;
    &lt;pre id=&quot;AUoX&quot;&gt;int n;
int f[n], rf[n];
for(int i = 1; i &amp;lt; n; i++){
    f[i] = mul(f[i - 1], i); //умножение чисел по модулю
}
rf[n - 1] = inv(f[n - 1]); //обратное число по модулю
for(int i = n - 2; i &amp;gt;= 0; i--){
    rf[i] = mul(rf[i + 1], i + 1); //умножение чисел по модулю
}&lt;/pre&gt;
    &lt;p id=&quot;74UA&quot;&gt;Мемы:&lt;br /&gt;1/n = (n - 1)! / n!&lt;br /&gt;N^-1 = f[N - 1] * rf[N] (mod M)&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;46Ko&quot;&gt;Задачка&lt;/h3&gt;
    &lt;p id=&quot;96fu&quot;&gt;Надо найти все простые числа на отрезке [L, R] &lt;br /&gt;(R-L+1 &amp;lt; 1e7)&lt;/p&gt;
    &lt;pre id=&quot;IP3C&quot;&gt;int l, r;
vector&amp;lt;int&amp;gt; primes; //предпосчитать
vector&amp;lt;bool&amp;gt; isPrime(r - l + 1, true);
for(auto &amp;amp;i : primes){
    for(int j = i * max((l + i - 1) / i, i); j &amp;lt;= r; j += i){
        isPrime[j - l] = false;
    }
}&lt;/pre&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;RUOh&quot;&gt;Линейное решето Эратосфена&lt;/h3&gt;
    &lt;pre id=&quot;9o4E&quot;&gt;int n;
vector&amp;lt;int&amp;gt; minDiv(n);
vector&amp;lt;int&amp;gt; primes;
iota(minDiv.begin(), minDiv.end(), 0);
for(int i = 2; i &amp;lt; n; i++){
    if(minDiv[i] == i){
        primes.pb(i);
    }
    for(auto &amp;amp;p : primes){
        if(p &amp;gt; minDiv[i] || p * i &amp;gt;= n){
            break;
        }
        minDiv[p * i] = p;
    }
}&lt;/pre&gt;
  &lt;/section&gt;

</content></entry><entry><id>lelyte:scanline_sirius</id><link rel="alternate" type="text/html" href="https://teletype.in/@lelyte/scanline_sirius?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=lelyte"></link><title>ScanLine ~ Сириус 04.06</title><published>2022-06-04T07:15:25.763Z</published><updated>2022-06-04T09:30:28.776Z</updated><category term="sirius-2022" label="Sirius 2022"></category><summary type="html">Задача заключается в том, что на плоскости имеется N прямоугольников,
стороны которых параллельны осям координат. Требуется вычислить площадь объединения данных прямоугольников</summary><content type="html">
  &lt;h3 id=&quot;dB0J&quot;&gt;КОНСПЕКТ ЕЩЕ ПИШЕТСЯ!!!&lt;/h3&gt;
  &lt;h3 id=&quot;uQHD&quot;&gt;Задача - Объединение прямоугольников&lt;/h3&gt;
  &lt;p id=&quot;qb3Y&quot;&gt;Задача заключается в том, что на плоскости имеется N прямоугольников,&lt;br /&gt;стороны которых параллельны осям координат. Требуется вычислить площадь объединения данных прямоугольников&lt;/p&gt;
  &lt;p id=&quot;7Tad&quot;&gt;Тупняк - Сделаем буловую табличку, по размеру достаточную, чтобы туда поместились все наши прямоугольники. Перебираем все прямоугольники. Смотрим на очередной. Поставим в табличку единички в те клетки, которые лежат в каждом прямоугольнике. Это работает за 𝒪(𝑛𝑆), где 𝑆 — площадь таблички, так как мы 𝑛 раз проходим по табличке площади 𝑆.&lt;/p&gt;
  &lt;p id=&quot;aCKO&quot;&gt;Решение за 𝒪(𝑛 log 𝑛) - Здесь мы сжимаем координаты.&lt;br /&gt;Теперь будем хранить одну вертикальную полоску длины, равной высоте таблицы. Хранить будем, как массив интов. Делаем сканалйн по 𝑥-ам. В этой полоске поддерживаем сколько из еще открытых прямоугольников имеют данную координату по 𝑥. Открылся новый прямоугольник — ко всем нужным 𝑦 в полоске прибавили единичку. Закрылся — вычитаем единичку. Чтобы найти площадь на текущем столбце, нужно сложить площади всех точек, в которых&lt;br /&gt;записан не ноль. Получили сложность 𝒪(𝑛2). Можно оптимизировать с помощью ДО на 𝒪(𝑛 log 𝑛)&lt;/p&gt;
  &lt;p id=&quot;g5Fs&quot;&gt;Так же ссылочка на решение челика на Codeforces - &lt;a href=&quot;https://codeforces.com/blog/entry/49797&quot; target=&quot;_blank&quot;&gt;https://codeforces.com/blog/entry/49797&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;Z8f2&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;b0TS&quot;&gt;Задача - Найти точку, накрытой наибольшим количеством прямоугольников&lt;/h3&gt;
  &lt;p id=&quot;CjKM&quot;&gt;Даны n прямоугольников. Надо найти точку, которая покрыта максимальным количеством прямоугольников.&lt;/p&gt;
  &lt;p id=&quot;BQd6&quot;&gt;Решение человека с Codeforces: &lt;/p&gt;
  &lt;p id=&quot;EdkC&quot;&gt;Давайте возьмем y-координаты всех точек, для которых нужно определить количество прямоугольников, покрывающих их, и отметим их на вертикальной прямой, находящейся в &lt;em&gt;x&lt;/em&gt; = - ∞. Давайте теперь начнем непрерывно двигать эту прямую до &lt;em&gt;x&lt;/em&gt; = + ∞ и поддерживать для каждой точки количество прямоугольников, покрывающих ее.&lt;/p&gt;
  &lt;p id=&quot;Dlpt&quot;&gt;Собственно, вопрос: а в какие моменты данные количества будут изменяться? Ответ: когда наша прямая &amp;quot;входит&amp;quot; в прямоугольник (то есть, проходит через координату &lt;em&gt;x&lt;/em&gt; = &lt;em&gt;xleft&lt;/em&gt; и когда она &amp;quot;выходит&amp;quot; из него (проходит через координату &lt;em&gt;x&lt;/em&gt; = &lt;em&gt;xright&lt;/em&gt;). Ну, собственно говоря, мы можем построить отсортированный массив т.н. &amp;quot;событий&amp;quot;, где события — это вход в прямоугольник, выход из прямоугольника и ответ на запрос количества покрывающих точку прямоугольников. Соответственно, для события входа в прямоугольник мы прибавляем единичку на отрезке [&lt;em&gt;ybottom&lt;/em&gt;; &lt;em&gt;ytop&lt;/em&gt;], для события выхода из прямоугольника — отнимаем единичку на соответствующем отрезке, а для события ответа на запрос — сохраняем значение количества покрывающих точку прямоугольников.&lt;/p&gt;
  &lt;p id=&quot;0594&quot;&gt;PS - &lt;a href=&quot;https://codeforces.com/blog/entry/49588&quot; target=&quot;_blank&quot;&gt;https://codeforces.com/blog/entry/49588&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;FBtO&quot;&gt;Так же решение человека с форума emaxx (в конце написан код, но как говорит автор, он с багами, но баги в ДО) - &lt;a href=&quot;https://e-maxx.ru/forum/viewtopic.php?id=368&quot; target=&quot;_blank&quot;&gt;https://e-maxx.ru/forum/viewtopic.php?id=368&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;HRcn&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;FZXh&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;R9JL&quot;&gt;Задача - Сумма на прямоугольнике&lt;/h3&gt;
  &lt;p id=&quot;PPKJ&quot;&gt;Решение - в конце конспект Сергея Слотина&lt;/p&gt;
  &lt;p id=&quot;e51k&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;ZROA&quot;&gt;Крутой конспект - &lt;a href=&quot;https://archive.lksh.ru/2018/august/B&quot; target=&quot;_blank&quot;&gt;https://archive.lksh.ru/2018/august/B&lt;/a&gt;&amp;#x27;/notes/03.pdf&lt;/p&gt;
  &lt;p id=&quot;wpcM&quot;&gt;Так же интересный конспект от Сергея Слотина - &lt;a href=&quot;https://ru.algorithmica.org/cs/decomposition/scanline/&quot; target=&quot;_blank&quot;&gt;https://ru.algorithmica.org/cs/decomposition/scanline/&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>lelyte:fenwick_tree</id><link rel="alternate" type="text/html" href="https://teletype.in/@lelyte/fenwick_tree?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=lelyte"></link><title>Тинькофф B' - Дерево Фенвика</title><published>2022-05-17T19:56:35.233Z</published><updated>2022-05-17T19:58:10.635Z</updated><category term="tinkoff-bp-2021-2022" label="Tinkoff Bp 2021-2022"></category><tt:hashtag>lelyte</tt:hashtag><tt:hashtag>fenwick_tree</tt:hashtag><summary type="html">Дерево Фенвика - структура данных, дерево на одномерном массиве, которая обладает такими свойствами, как:</summary><content type="html">
  &lt;tt-tags id=&quot;yOH7&quot;&gt;
    &lt;tt-tag name=&quot;lelyte&quot;&gt;#lelyte&lt;/tt-tag&gt;
    &lt;tt-tag name=&quot;fenwick_tree&quot;&gt;#fenwick_tree&lt;/tt-tag&gt;
  &lt;/tt-tags&gt;
  &lt;p id=&quot;PwRO&quot;&gt;&lt;strong&gt;&lt;em&gt;Дерево Фенвика&lt;/em&gt;&lt;/strong&gt; - структура данных, дерево на одномерном массиве, которая обладает такими свойствами, как:&lt;/p&gt;
  &lt;ol id=&quot;Xn3C&quot;&gt;
    &lt;li id=&quot;wE7l&quot;&gt;Сумма на отрезке с L по R&lt;/li&gt;
    &lt;li id=&quot;Sugh&quot;&gt;Изменение значения в какой-то позиции за O(LogN)&lt;/li&gt;
    &lt;li id=&quot;ekYe&quot;&gt;Требует O(N) памяти &lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;T7q8&quot;&gt;Код взятия суммы на отрезке: (массив f - наше дерево)&lt;/p&gt;
  &lt;pre id=&quot;Dh18&quot;&gt;ll get_sum(ll i){
    ll ans = 0;
    for(; i &amp;gt;= 0; i = (i&amp;amp;(i+1))-1){
        ans += f[i];
    }
    return ans;
}


ll sum_otr(ll l, ll r){
    return get_sum(r) - get_sum(l-1);
}&lt;/pre&gt;
  &lt;p id=&quot;2CzP&quot;&gt;Обновление на точке:&lt;/p&gt;
  &lt;pre id=&quot;IyTQ&quot;&gt;void update(ll i, ll x){
    for(; i &amp;lt; n; i = (i | (i+1))){
        f[i] += x;
    }
}&lt;/pre&gt;
  &lt;p id=&quot;5xvc&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;lJHg&quot;&gt;Так же Дерево Фенвика можно сделать двумерным (подробности - &lt;a href=&quot;https://e-maxx.ru/algo/fenwick_tree&quot; target=&quot;_blank&quot;&gt;https://e-maxx.ru/algo/fenwick_tree&lt;/a&gt;)&lt;/p&gt;

</content></entry></feed>