CueIndex
A start-sorted cue list plus the small amount of derived data that makes lookups fast.
CueSelector answers the same questions and is the definition of what the answers ARE, but it walks the list from the beginning every time. That is free for a film with a few hundred lines and it is not free for the dense typeset ASS tracks this engine is expected to survive, which run to about seventy thousand cues: near the end of one of those, every timing edge costs seventy thousand comparisons, and there is a timing edge on every subtitle pass.
This holds the same list, unchanged, next to one extra array: the largest end time seen among the cues up to each position. That is what makes a backward walk terminable. Finding the last cue that could have started is a binary search; from there the walk backward can stop the moment the prefix maximum says no earlier cue can still be showing, which for ordinary subtitles is after a step or two and in the worst case is no worse than the scan it replaces.
Built once per cue table. The engine replaces that table wholesale on a track change, so nothing here is ever invalidated in place, and CueSelector stays pure for anyone who wants the rule without the index.
Functions
Cues visible at atMicros, in draw order. The same answer CueSelector.activeAt gives.
The next instant after atMicros at which the active set changes, or null when it never does.
Points this index at cues, reusing what it already computed when it can.