Я понял вашу проблему как:
У каждого сегмента есть внутренний порядок, а у самих блоков порядок, поэтому все элементы имеют некоторый порядок, и вам нужен i-й элемент в этом порядке.
Чтобы решить это:
Что вы можете сделать, это сохранить дерево «накопленных значений», где узлы листа (x1, x2, ..., xn) являются размерами сегмента.Значение узла - это сумма значений его непосредственных потомков.Если оставить значение 2, то все будет просто (вы всегда можете заполнить его сегментами нулевого размера в конце), и дерево будет полным деревом.
В соответствии с каждым баком вы будете поддерживать указатель на соответствующийлистовой узел.
Например, скажем, размеры сегмента 2,1,4,8.
Дерево будет выглядеть так:
15
/ \
3 12
/ \ / \
2 1 4 8
Если вы хотите общее количествопрочитайте значение корневого узла.
Если вы хотите изменить некоторый xk (т.е. изменить соответствующий размер сегмента), вы можете пройти вверх по дереву, следуя указателям родителя, обновляя значения.
Например, если вы добавите 4 элемента во второе ведро, это будет (узлы, отмеченные * - это те, которые изменились)
19*
/ \
7* 12
/ \ / \
2 5* 4 8
Если вы хотите найти i-й элемент, вы идете по вышеприведенному дереву., эффективно делающий бинарный поиск.У вас уже есть левый ребенок и правый ребенок.Если я> значение левого дочернего узла текущего узла, вычтите значение левого дочернего узла и выполните рекурсию в правом дереве.Если i <= значение левого дочернего узла, вы идете налево и снова выполняете рекурсию. </p>
Скажем, вы хотели найти 9-й элемент в вышеприведенном дереве:
Поскольку левый дочерний элемент root равен 7 <9. Вы вычитаете 7 из 9 (чтобы получить 2) и идете направо. </p>
Поскольку 2 <4 (левый потомок 12), вы идете налево. </p>
Вы находитесь на листовом узле, соответствующемв третье ведро.Теперь вам нужно выбрать второй элемент в этом сегменте.
Если вам нужно добавить новый блок, вы удваиваете размер своего дерева (при необходимости), добавляя новый корень, делая существующее дерево левым.child и добавьте новое дерево со всеми нулевыми сегментами, кроме того, которое вы добавили (который мы будем самым левым листом нового дерева).Это будет амортизироваться O (1) раз для добавления нового значения в дерево.Предостережение заключается в том, что вы можете добавить только ведро в конце, а не где-то посередине.
Получение общего количества равно O (1).Обновление отдельного сегмента / поиска элемента - O (logn).
Добавление нового сегмента амортизируется O (1).
Использование пространства равно O (n).
Вместо двоичного дерева вы, вероятно, можете сделать то же самое сB-Tree.