code: def _build_index(self):
          
          row0 = list(map(len, self._lists))
  
          if len(row0) == 1:
              self._index[:] = row0
              self._offset = 0
              return
  
          head = iter(row0)
          tail = iter(head)
          row1 = list(starmap(add, zip(head, tail)))
  
          if len(row0) & 1:
              row1.append(row0[-1])
  
          if len(row1) == 1:
              self._index[:] = row1 + row0
              self._offset = 1
              return
  
          size = 2 ** (int(log_e(len(row1) - 1, 2)) + 1)
          row1.extend(repeat(0, size - len(row1)))
          tree = [row0, row1]
  
          while len(tree[-1]) > 1:
              head = iter(tree[-1])
              tail = iter(head)
              row = list(starmap(add, zip(head, tail)))
              tree.append(row)
  
          reduce(iadd, reversed(tree), self._index)
          self._offset = size * 2 - 1
docs: Build an index for indexing the sorted list.
  
          Indexes are represented as binary trees in a dense array notation
          similar to a binary heap.
  
          For example, given a _lists representation storing integers:
  
          [0]: 1 2 3
          [1]: 4 5
          [2]: 6 7 8 9
          [3]: 10 11 12 13 14
  
          The first transformation maps the sub-lists by their length. The
          first row of the index is the length of the sub-lists.
  
          [0]: 3 2 4 5
  
          Each row after that is the sum of consecutive pairs of the previous row:
  
          [1]: 5 9
          [2]: 14
  
          Finally, the index is built by concatenating these lists together:
  
          _index = 14 5 9 3 2 4 5
  
          An offset storing the start of the first row is also stored:
  
          _offset = 3
  
          When built, the index can be used for efficient indexing into the list.
          See the comment and notes on self._pos for details.