Недавно была следующая задача представлена на школьном BSUIR OPEN XIII:
Дан массив целых чисел и запросы изменения в точке. Нужно после каждого такого запроса отвечать в онлайне: сколько существует таких пар $$$i, j$$$, которую дают максимально возможную сумму и находятся на расстоянии не больше $$$k$$$.
Без онлайна — это почти баян с Канадской олимпиады для школьников (решается при помощи DCP-offline), но научимся делать в онлайне. По сути, я хочу научиться делать структуру данных, которая умеет учитывать каждую такую пару ровно один раз. Лично я умею ее делать за $$$log(n)$$$ на запрос.
Давайте дополним дерево отрезков до степени двойки (иначе работать не будет). Тогда у нас будет какое-то количество уровней, и при том, на каждом уровне у нас одиннаковое количество вершин. Тогда для удобство обозначим за $$$l_v, r_v$$$ это отрезок, за который отвечает поддерево, а за $$$lvl_{i, j}$$$ — вершину на $$$i$$$ уровнем под номером $$$j$$$ (у нас вершины на одном уровне идут в порядке возрастания правой границы). Также посчитаем за $$$nxt_v$$$ — самую последнюю вершину на уровне вершины $$$v$$$, для которой выполняется, что $$$r_{nxt} - r_v \leq k$$$ (другими словами, это самая дальняя вершина на уровне, для которой любая пара из этих поддеревьев образует подходящую пару)
Тогда утверждение, достаточно рассмотреть все пары в следующих поддеревьев:
Для каждой вершины $$$v$$$ скажем, что ответ для нее — это максимум ответа из левого/правого поддерева, а также рассмотреть оптимум в парах поддеревьев $$$v, nxt_v$$$, а также $$$v, 'nxt_v$$$, где $$$'nxt_v$$$ — это первая вершина левее на уровне $$$nxt_v$$$. А также взять два оптимума для поддерева размера $$$\leq k$$$.
Теперь как учесть каждую пару ровно один раз — мы не будет мержить две вершины, если у них предки тоже подходят (то есть, максимальное расстояние между парами вершин будет меньше или равно $$$k$$$). А вот этот факт уже очевидный.
Доказательство: проходит стрессы, а значит верно. Так как размеры всех деревьев степени двойки, и при том условие везде одиннаковое, то этот пересчет будет только на одном уровне (когда мы учитываем, что если предки подошли, то эту пару не учитываем). И при том, в этом случае будет задействованы не более $$$3$$$ вершин на этом уровне. (Иначе их предки были бы тоже актуальны). А в этом случае, данный алгоритм действительно каждую пару учтет ровно один раз, так как это будут все актуальные пары. А единственность очевидна, поэтому оставлю ее на доказательство читателя.
Мы научились учитывать каждую пару ровно один раз. Теперь нужно научиться обновлять делать изменение в точке. Давайте заметим, что при изменении вершины ответ поменяется только у предков, а это тривиально делается, а также у вершин, для которых наша была в качестве одного из двух правых. Мы эти вершины можем легко предпосчитать. А поэтому, мы должны пересчитать у них ответ, а затем рекурсивно обновить их родителей. И ввиду того, что нам нужно обновлять еще и родителей, то и получается $$$log^2$$$ (при том достаточно долгий, так как сам код пересчета достаточно тяжелый). (Либо же если аккуратно посмотреть доказательство, то у нас изменятся не так много интересных вершин дерева отрезков и получится $$$log$$$, но ниже предоставлена реализация за $$$log^2$$$)













