Skip to main content

Sorted Containers

A sorted container maintains a collection of elements in sorted order while supporting insertion, deletion, and order-based queries such as rank (how many elements are strictly less than a given value) and positional access. Balanced BSTs, skip lists, and bucket-based structures all fit this role.

In competitive programming the simplest portable implementation is a plain Python list kept sorted via bisect. Insertions and deletions are O(n)O(n) because of the underlying array shifts, but bisect_left gives O(logn)O(\log n) rank queries, which is usually what matters. The example replays a script of add, remove, and rank operations and returns the rank answers in order.

Codes

import bisect

def solve(xs):
ops = xs
data = []
answers = []
for op in ops:
kind = op[0]
v = op[1]
if kind == "add":
bisect.insort(data, v)
elif kind == "remove":
i = bisect.bisect_left(data, v)
if i < len(data) and data[i] == v:
data.pop(i)
else: # "rank"
answers.append(bisect.bisect_left(data, v))
return answers

Example

Loading Python runner...

Description

Run time analysis

O(logn)O(\log n) for each rank query, since bisect_left runs a plain binary search over the sorted list. add and remove are O(n)O(n) in the worst case because inserting or deleting in a Python list shifts the tail; a true balanced-BST or order-statistic tree brings those down to O(logn)O(\log n).

Space analysis

O(n)O(n) total for the list of live elements. Each operation uses only O(1)O(1) auxiliary state.

Proof of correctness

The list data is kept sorted as a loop invariant. bisect.insort finds the unique index ii with data[i-1] <= v <= data[i] and inserts vv there, so the list remains sorted. remove calls bisect_left(data, v) which returns the first index whose value is not less than vv; if that slot equals vv deleting it removes one occurrence while preserving the order. For a rank query, bisect_left(data, v) returns the number of elements strictly less than vv because it is the smallest index ii with data[i] >= v, and all earlier entries are strictly smaller by the invariant.

Extensions

Applications

References