STL provides binary search functions std::lower_bound and std::upper_bound, but I tend not to use them because I\'ve been unable to remember what they do, because their contract
the source code actually has a second explanation which I found very helpful to understand the meaning of the function:
lower_bound: Finds the first position in which [val] could be inserted without changing the ordering.
upper_bound: Finds the last position in which [val] could be inserted without changing the ordering.
this [first, last) forms a range which the val could be inserted but still keep the original ordering of the container
lower_bound return "first" i.e. find the "lower boundary of the range"
upper_bound return "last" i.e. find the "upper boundary of the range"