(Я собираюсь ответить на красно-черное дерево вместо дерева 2-3, так как его легче рассуждать. Этот ответ требует небольшой адаптации для работы с деревом 2-3)
Вместо того, чтобы каждая вершина сохраняла количество элементов слева, пусть каждая вершина хранит количество элементов в поддереве, корнем которого она является.При перемещении вниз по дереву от корня сохраняйте накопленную сумму s элементов, которые у вас есть с левой стороны.Всякий раз, когда вы перемещаетесь к правому дочернему элементу вершины v , добавляйте количество элементов в поддереве левого дочернего элемента v к s .
Этот инвариант не нуждается в обновлении при объединении или разбиении двух списков.
Чтобы объединить два списка A и B (то есть B добавляется к A ), просто создайте новую вершину v и сделайте A и B левойи правильные дети соответственно.Обновите число элементов в поддереве с корнем в v , чтобы оно стало суммой количества элементов в A и B .
Twoразделите список на два, просто удалите ребро, идущее к корню списка, который вы хотите вырезать.
(ОБНОВЛЕНИЕ)
Однако в зависимости от размера списков дерево может стать неуравновешенным.После определенного количества «несбалансированных» конкатенаций или разбиений вам придется перебалансировать дерево.Я должен признать, я не совсем уверен, какова временная сложность этого.Я почти уверен, что вы не можете получить амортизированное постоянное время, но вы можете получить амортизированное время O (log n).