Lower and Upper Bound
Binary Search templates for duplicate ranges and insertion positions
Search for a boundary, not an exact match
lower_bound returns the first position whose value is at least the target. upper_bound returns the first position whose value is greater. Their half-open range [lo, hi) allows hi = n, so insertion after the final value needs no special case.
One comparison changes the meaning
Lower bound moves right while a[mid] < target. Upper bound also moves right on equality, using a[mid] <= target. The player runs both searches over the same duplicate-heavy array, then highlights the equal range [lower, upper).
lower_bound: start with half-open range [0, 10) (hi=n sentinel) for target 2.
Reliable library semantics
Each boundary takes O(log n) time and O(1) space. If the target is absent, lower and upper meet at the same insertion position and the count is zero. This is the behavior behind C++ lower_bound, Python bisect, and equivalent standard-library APIs.
lo are known to fail the boundary predicate, while indices at or after hi are known to satisfy it. Review exact-match behavior first in Binary Search.