Если вам нужно внести изменения с произвольным доступом: дерево, как в ответе v3. Найдите нижнюю часть диапазона с помощью поиска, затем посчитайте вверх. Вставка или удаление узла - это O (log N). stbuton делает хорошее замечание, что если вы хотите разрешить дублирование (как это представляется возможным для событий с метками дат), то вам не нужен набор на основе дерева.
Если вам не нужно вносить изменения с произвольным доступом: отсортированный массив (или вектор или что-то еще). Найдите место начала диапазона с помощью бинарной отбивки, затем посчитайте вверх. Вставка или удаление - O (N) в середине. Дубликаты просты.
Алгоритмическая производительность поиска одинакова в обоих случаях: O (M + log N), где M - размер диапазона. Но массив использует меньше памяти для каждой записи, и может быть быстрее для подсчета в диапазоне, потому что после двоичного преобразования это просто прямой последовательный доступ к памяти, а не следующие указатели.
В обоих случаях вы можете сделать так, чтобы вставка в конце была (амортизирована) O (1). Для дерева сохраните запись конечного элемента в заголовке, и вы получите оценку O (1). Для массива вырастите по экспоненте, и вы получите амортизированный O (1). Это полезно, если вносимые вами изменения всегда или почти всегда «добавляют новое событие с текущим временем», поскольку время (как вы надеетесь) неубывающее количество. Если вы используете системное время, то, конечно, вам придется проверять, чтобы избежать аварий, когда часы сбрасываются назад.
Альтернативный ответ: таблица SQL, и пусть база данных оптимизирует, как она хочет. А структура Google BigTable специально разработана для быстрого выполнения запросов, гарантируя, что результат любого запроса всегда будет последовательной последовательностью из предварительно подготовленного индекса: -)