#include <iostream>

using namespace std;

const int N = 2001;
int n, m;
int x[N], y[N];

// Given a value z, count the number of products x[i] * y[j] that are less than
// or equal to z.
// Notice that this function uses O(1) memory!
int count(int z) {
    int ans = 0;
    // Loop through all pairs, counting the products which are less than or
    // equal to z.
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (x[i] * y[j] <= z) {
                ans++;
            }
        }
    }
    return ans;
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> x[i];
    }
    for (int j = 0; j < m; j++) {
        cin >> y[j];
    }

    // Run binary search to find the median.
    // First, determine the initial search space.
    // The median is definitely bigger than the smallest value, and definitely
    // smaller than the biggest value, so find what these are.
    const int INFINITY = 1e9;
    int l = INFINITY, r = -INFINITY;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            l = min(l, x[i] * y[j]);
            r = max(r, x[i] * y[j]);
        }
    }
    
    // We want to find the smallest value of z such that there are at least ceil(n * m / 2)
    // elements less than or equal to z. This is exactly the median.
    int ans = -1;
    while (l <= r) {
        // Guess a value for z.
        int mid = (l + r) / 2;
        if (count(mid) >= (n * m + 1) / 2) {
            // z >= the median.
            // Search smaller values.
            ans = mid;
            r = mid - 1;
        } else {
            // z < the median.
            // Search larger values.
            l = mid + 1;
        }
    }
    cout << ans << endl;
    return 0;
}
