Replace vector<int> const& and int size with an array_view<const int>.
An array_view<T> is a class that stores a pair of pointers (b and e), and exposes [] and .size() and begin() and end() and front() and back() and empty(). It has implicit constructors from std::vector<T>&, std::vector<remove_const_T> const&, T(&)[N], std::array<T,N>&, std::array<remove_const_T,N>const&, and from T*, T* and T*, size_t.
Methods like array_view<T> without_front(size_t=1) and array_view<T> without_back(size_t=1) are also useful.
There is a std::experimental::array_view that also supports multi-dimensional arrays, or you can roll your own. Here is one I posted on stack overflow, where it solves a different problem. It doesn't have without_front, but that is easy to write (it depends on how safe you want it to be -- I'd go for fully safe, where it refuses to return a malformed array view and instead returns an empty one, because the check is cheap).
Use looks like:
int find_kth(array_view<int const> a, array_view<int const> b, int k){
// ...
find_kth(a, b.without_front(j), k-j);
// ...
}
which I find slick. If you want to pass raw arrays, just {arr, size} and it becomes an array_view. If you want to pass a vector, it implicitly converts.