Optimized Binary Search in with Explanation 
IntuitionApproachComplexity
Time complexity: O((m + n) * log (hi - lo))

Space complexity: O(m + n)
Code
# Intuition
<!-- Describe your first thoughts on how to solve this problem. -->

# Approach
<!-- Describe your approach to solving the problem. -->

# Complexity
- Time complexity: O((m + n) * log (hi - lo))
<!-- Add your time complexity here, e.g. $$O(n)$$ -->

- Space complexity: O(m + n)
<!-- Add your space complexity here, e.g. $$O(n)$$ -->

# Code
```python3 []
class Solution:
    def kthSmallestProduct(self, nums1: List[int], nums2: List[int], k: int) -> int:
        def get_count(target):
            nonlocal neg1, pos1, neg2, pos2

            # there are four combinations to count for : (neg1, neg2), (neg1, pos2), (pos1, neg2), (pos1, pos2)
            res = 0

            # case1; (neg1, neg2)
            i = len(neg1) - 1            # i starts from tail of neg1 (maximum value)
            j = 0                        # j starts from the head of neg2 (minimum value)
            while i >= 0 and j < len(neg2):

                # found a valid pair; anything comes after j in neg2 can be paired with neg1[i]
                if neg1[i] * neg2[j] <= target:
                    # count all the values after j
                    res += (len(neg2) - j)

                    # i is fully covered; decrease it then
                    i -= 1
                else:
                    j += 1

            # case2; (neg1, pos2)
            i = 0                       # i starts from head of neg1 (minimum value)
            j = 0                       # j starts from the head of pos2 (minimum value)
            while i < len(neg1) and j < len(pos2):

                # found a valid pair; anything comes after j in pos2 can be paired with neg1[i]
                if neg1[i] * pos2[j] <= target:
                    res += (len(pos2) - j)

                    # i is fully covered; increase it then
                    i += 1
                else:
                    j += 1

            # case 3; (pos1, neg2)
            i = len(pos1) - 1          # i starts from tail of pos1 (maximum value)
            j = len(neg2) - 1          # j starts from tail of neg2 (maximum value)
            while i >= 0 and j >= 0:

                # found a valid pair; anything comes before j in pos2 can be paired with neg1[i]
                if pos1[i] * neg2[j] <= target:
                    res += (j + 1)

                    # i is fully covered; decrease it then
                    i -= 1
                else:
                    j -= 1

            # case4; (pos1, pos2)
            i = 0                    # i starts from head of pos1 (minimum value)
            j = len(pos2) - 1        # j starts from tail of pos2 (maximum value)
            while i < len(pos1) and j >= 0:

                # found a valid pair; anything comes before j in pos2 can be paired with pos1[i]
                if pos1[i] * pos2[j] <= target:
                    res += (j + 1)
                
                    # i is fully covered; increase it then
                    i += 1
                else:
                    j -= 1

            return res

        # 1. split nums1 into neg1 & pos1 arrays
        neg1 = [num for num in nums1 if num < 0]
        pos1 = nums1[len(neg1):]

        # 2. split nums2 into neg2 & pos2 arrays
        neg2 = [num for num in nums2 if num < 0]
        pos2 = nums2[len(neg2):]

        # 3. calculate lower & upper bounds for the product of values
        lo = min(nums1[0] * nums2[0], nums1[-1] * nums2[0], 
                 nums1[0] * nums2[-1], nums1[-1] * nums2[-1])
    
        hi = max(nums1[0] * nums2[0], nums1[-1] * nums2[0], 
                nums1[0] * nums2[-1], nums1[-1] * nums2[-1])

        # 4. run binary search till reaching the right pair
        while lo <= hi:
            mid = (lo + hi) // 2
        
            # count the number of valid indices for product value of mid
            count = get_count(mid)
        
            # infeasible; search the right side
            if count < k:
                lo = mid + 1
            
            # feasible; search the left side
            else:
                hi = mid - 1

        return lo
```
['Array', 'Binary Search', 'Python', 'Python3']