An easy way to do this is to maintain two sorted containers, one lower than the median, one greater.
When you find a new element, see what container to insert it into (so that all elements of lower are always less than or equal to all elements of upper), then rebalance counts so that the median is "in the gap" between them.
Yours sort of does this, but defines the lower range to be [.begin(), it) and the upper to be [it, .end()). I'd make them separate containers to reduce the amount of state you need to keep in your head to understand the code, unless performance was particularly important.
Maintain two sorted containers, low and high, with the following invariants:
low.size() is the same as high.size() or 1 larger
- Every element of
low is less than or equal to every element of high.
Then the median of low union high is low.last().
Assuming you have such a pair of containers, if you wanted to add an element x, I would first maintain invariant 2 -- if low.empty() or x <= low.last(), stick it in low, otherwise stick it in high.
Next, maintain invariant 1: if high has more elements than low, remove the lowest element from high and add it to low. If low has 2 more elements than high, remove the highest element from low and add it to high.
If we started with a low and high that obeyed the above two invariants, then after the above steps we still have a low and high that obeys these two invariants. And when the above two invariants hold, the median is low.last()!