The naming of the variables/function parameters is really bad. If the person who wrote this code had bothered with creating more descriptive names the code could have self-documented what was going on.
string rec(int lower_bounds, int upper_bounds, int arr[], int arr_size) for example.
Using single letter variable names in a for loop is acceptable, because the scope is more restrictive.
It also has historical reasons.
"It's always been done that way" shouldn't be an excuse for not self-documenting code with good explanatory variable names.
> int m = (l+r)/2;
This should be written as int m = l + (r-l)/2;
The former is basically the world's oldest overflow bug waiting to happen.
Having arrays of billions of items is easy to do now, especially on 64-bit architectures.
So it's all too easy to end up with an array that would overflow integer arithmetic.
> int a[n];
This isn't valid C++.
Use new[] or a std::vector.