Problem: Warning: This problem has an unusual memory limit!

Bob decided that he will not waste his prime years implementing GUI forms for a large corporation and instead will earn his supper on the Stock Exchange Reykjavik. The Stock Exchange Reykjavik is the only actual stock exchange in the world. The only type of transaction is to take a single share of stock x and exchange it for a single share of stock y, provided that the current price of share x is at least the current price of share y. 

There are 2n stocks listed on the SER that are of interest to Bob, numbered from 1 to 2n. Bob owns a single share of stocks 1 through n and would like to own a single share of each of n+1 through 2n some time in the future.

Bob managed to forecast the price of each stock — in time t ≥ 0, the stock i will cost a_i ⋅ ⌊ t ⌋ + b_i. The time is currently t = 0. Help Bob find the earliest moment in time in which he can own a single share of each of n+1 through 2n, and the minimum number of stock exchanges he has to perform in order to do that.

You may assume that the Stock Exchange has an unlimited amount of each stock at any point in time. 

Input

The first line contains a single integer n (1 ≤ n ≤ 2200) — the number stocks currently owned by Bob.

Each of the next 2n lines contains integers a_i and b_i (0 ≤ a_i, b_i ≤ 10^9), representing the stock price of stock i. 

Output

If it is impossible for Bob to achieve his goal, output a single integer -1.

Otherwise, output two integers T and E, where T is the minimum time in which he can achieve his goal, and E is the minimum number of exchanges in which he can achieve his goal at time T.

Examples

Input


1
3 10
1 16


Output


3 1


Input


2
3 0
2 1
1 10
1 11


Output


6 3


Input


1
42 42
47 47


Output


-1


Input


8
145 1729363
891 4194243
424 853731
869 1883440
843 556108
760 1538373
270 762781
986 2589382
610 99315884
591 95147193
687 99248788
65 95114537
481 99071279
293 98888998
83 99764577
769 96951171


Output


434847 11


Input


8
261 261639
92 123277
271 131614
320 154417
97 258799
246 17926
117 222490
110 39356
85 62864876
86 62781907
165 62761166
252 62828168
258 62794649
125 62817698
182 62651225
16 62856001


Output


1010327 11

Note

In the first example, Bob simply waits until time t = 3, when both stocks cost exactly the same amount.

In the second example, the optimum strategy is to exchange stock 2 for stock 1 at time t = 1, then exchange one share of stock 1 for stock 3 at time t = 5 (where both cost 15) and then at time t = 6 exchange the second on for the stock number 4 (when they cost 18 and 17, respectively). Note that he can achieve his goal also with only two exchanges, but this would take total time of t = 9, when he would finally be able to exchange the share number 2 for the share number 3. 

In the third example, Bob can never achieve his goal, as the second stock is always strictly more expensive than the first one.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
inline int read() {
  char ch = getchar();
  int nega = 1;
  while (!isdigit(ch)) {
    if (ch == '-') nega = -1;
    ch = getchar();
  }
  int ans = 0;
  while (isdigit(ch)) {
    ans = ans * 10 + ch - 48;
    ch = getchar();
  }
  if (nega == -1) return -ans;
  return ans;
}
void print(vector<int> x) {
  for (int i = 0; i < (int)x.size(); i++)
    printf("%d%c", x[i], " \n"[i == (int)x.size() - 1]);
}
int a[100005], b[100005], id[100005], n;
long long getval(int x, int id) { return 1LL * x * a[id] + b[id]; }
namespace atcoder {
namespace internal {
template <class E>
struct csr {
  std::vector<int> start;
  std::vector<E> elist;
  csr(int n, const std::vector<std::pair<int, E>>& edges)
      : start(n + 1), elist(edges.size()) {
    for (auto e : edges) {
      start[e.first + 1]++;
    }
    for (int i = 1; i <= n; i++) {
      start[i] += start[i - 1];
    }
    auto counter = start;
    for (auto e : edges) {
      elist[counter[e.first]++] = e.second;
    }
  }
};
}  // namespace internal
}  // namespace atcoder
namespace atcoder {
namespace internal {
template <class T>
struct simple_queue {
  std::vector<T> payload;
  int pos = 0;
  void reserve(int n) { payload.reserve(n); }
  int size() const { return int(payload.size()) - pos; }
  bool empty() const { return pos == int(payload.size()); }
  void push(const T& t) { payload.push_back(t); }
  T& front() { return payload[pos]; }
  void clear() {
    payload.clear();
    pos = 0;
  }
  void pop() { pos++; }
};
}  // namespace internal
}  // namespace atcoder
namespace atcoder {
template <class Cap, class Cost>
struct mcf_graph {
 public:
  mcf_graph() {}
  mcf_graph(int n) : _n(n) {}
  int add_edge(int from, int to, Cap cap, Cost cost) {
    assert(0 <= from && from < _n);
    assert(0 <= to && to < _n);
    assert(0 <= cap);
    assert(0 <= cost);
    int m = int(_edges.size());
    _edges.push_back({from, to, cap, 0, cost});
    return m;
  }
  struct edge {
    int from, to;
    Cap cap, flow;
    Cost cost;
  };
  edge get_edge(int i) {
    int m = int(_edges.size());
    assert(0 <= i && i < m);
    return _edges[i];
  }
  std::vector<edge> edges() { return _edges; }
  std::pair<Cap, Cost> flow(int s, int t) {
    return flow(s, t, std::numeric_limits<Cap>::max());
  }
  std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
    return slope(s, t, flow_limit).back();
  }
  std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
    return slope(s, t, std::numeric_limits<Cap>::max());
  }
  std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
    assert(0 <= s && s < _n);
    assert(0 <= t && t < _n);
    assert(s != t);
    int m = int(_edges.size());
    std::vector<int> edge_idx(m);
    auto g = [&]() {
      std::vector<int> degree(_n), redge_idx(m);
      std::vector<std::pair<int, _edge>> elist;
      elist.reserve(2 * m);
      for (int i = 0; i < m; i++) {
        auto e = _edges[i];
        edge_idx[i] = degree[e.from]++;
        redge_idx[i] = degree[e.to]++;
        elist.push_back({e.from, {e.to, -1, e.cap - e.flow, e.cost}});
        elist.push_back({e.to, {e.from, -1, e.flow, -e.cost}});
      }
      auto _g = internal::csr<_edge>(_n, elist);
      for (int i = 0; i < m; i++) {
        auto e = _edges[i];
        edge_idx[i] += _g.start[e.from];
        redge_idx[i] += _g.start[e.to];
        _g.elist[edge_idx[i]].rev = redge_idx[i];
        _g.elist[redge_idx[i]].rev = edge_idx[i];
      }
      return _g;
    }();
    auto result = slope(g, s, t, flow_limit);
    for (int i = 0; i < m; i++) {
      auto e = g.elist[edge_idx[i]];
      _edges[i].flow = _edges[i].cap - e.cap;
    }
    return result;
  }

 private:
  int _n;
  std::vector<edge> _edges;
  struct _edge {
    int to, rev;
    Cap cap;
    Cost cost;
  };
  std::vector<std::pair<Cap, Cost>> slope(internal::csr<_edge>& g, int s, int t,
                                          Cap flow_limit) {
    std::vector<std::pair<Cost, Cost>> dual_dist(_n);
    std::vector<int> prev_e(_n);
    std::vector<bool> vis(_n);
    struct Q {
      Cost key;
      int to;
      bool operator<(Q r) const { return key > r.key; }
    };
    std::vector<int> que_min;
    std::vector<Q> que;
    auto dual_ref = [&]() {
      for (int i = 0; i < _n; i++) {
        dual_dist[i].second = std::numeric_limits<Cost>::max();
      }
      std::fill(vis.begin(), vis.end(), false);
      que_min.clear();
      que.clear();
      size_t heap_r = 0;
      dual_dist[s].second = 0;
      que_min.push_back(s);
      while (!que_min.empty() || !que.empty()) {
        int v;
        if (!que_min.empty()) {
          v = que_min.back();
          que_min.pop_back();
        } else {
          while (heap_r < que.size()) {
            heap_r++;
            std::push_heap(que.begin(), que.begin() + heap_r);
          }
          v = que.front().to;
          std::pop_heap(que.begin(), que.end());
          que.pop_back();
          heap_r--;
        }
        if (vis[v]) continue;
        vis[v] = true;
        if (v == t) break;
        Cost dual_v = dual_dist[v].first, dist_v = dual_dist[v].second;
        for (int i = g.start[v]; i < g.start[v + 1]; i++) {
          auto e = g.elist[i];
          if (!e.cap) continue;
          Cost cost = e.cost - dual_dist[e.to].first + dual_v;
          if (dual_dist[e.to].second - dist_v > cost) {
            Cost dist_to = dist_v + cost;
            dual_dist[e.to].second = dist_to;
            prev_e[e.to] = e.rev;
            if (dist_to == dist_v) {
              que_min.push_back(e.to);
            } else {
              que.push_back(Q{dist_to, e.to});
            }
          }
        }
      }
      if (!vis[t]) {
        return false;
      }
      for (int v = 0; v < _n; v++) {
        if (!vis[v]) continue;
        dual_dist[v].first -= dual_dist[t].second - dual_dist[v].second;
      }
      return true;
    };
    Cap flow = 0;
    Cost cost = 0, prev_cost_per_flow = -1;
    std::vector<std::pair<Cap, Cost>> result = {{Cap(0), Cost(0)}};
    while (flow < flow_limit) {
      if (!dual_ref()) break;
      Cap c = flow_limit - flow;
      for (int v = t; v != s; v = g.elist[prev_e[v]].to) {
        c = std::min(c, g.elist[g.elist[prev_e[v]].rev].cap);
      }
      for (int v = t; v != s; v = g.elist[prev_e[v]].to) {
        auto& e = g.elist[prev_e[v]];
        e.cap += c;
        g.elist[e.rev].cap -= c;
      }
      Cost d = -dual_dist[s].first;
      flow += c;
      cost += c * d;
      if (prev_cost_per_flow == d) {
        result.pop_back();
      }
      result.push_back({flow, cost});
      prev_cost_per_flow = d;
    }
    return result;
  }
};
}  // namespace atcoder
namespace Flow {
struct Edge {
  int v, cap, nxt;
};
Edge edge[100005 * 2];
int first[100005], cur[100005], ss, dep[100005];
inline void init() {
  memset(first, 0, sizeof(first));
  ss = 1;
}
inline void add(int u, int v, int w) {
  edge[++ss] = (Edge){v, w, first[u]};
  first[u] = ss;
  edge[++ss] = (Edge){u, 0, first[v]};
  first[v] = ss;
}
int q[100005], l, r;
int s, t;
bool bfs() {
  for (int i = 1; i <= t; i++) dep[i] = 0;
  int l = 1, r = 1;
  q[1] = s, dep[s] = 1;
  while (l <= r) {
    int u = q[l++];
    for (int i = first[u]; i != 0; i = edge[i].nxt) {
      if (!edge[i].cap) continue;
      int v = edge[i].v;
      if (!dep[v]) dep[v] = dep[u] + 1, q[++r] = v;
      if (v == t) return 1;
    }
  }
  return dep[t];
}
int dfs(int u, int flow) {
  if (u == t || flow == 0) return flow;
  int ans = 0;
  for (int& i = cur[u]; i != 0; i = edge[i].nxt) {
    if (!edge[i].cap) continue;
    int v = edge[i].v;
    if (dep[v] != dep[u] + 1) continue;
    int go = dfs(v, min(flow, edge[i].cap));
    if (go) {
      flow -= go, ans += go;
      edge[i].cap -= go, edge[i ^ 1].cap += go;
    }
    if (!flow) return ans;
  }
  return ans;
}
int dinic() {
  int ans = 0;
  while (bfs()) {
    for (int i = 1; i <= t; i++) cur[i] = first[i];
    ans += dfs(s, 0x3f3f3f3f);
  }
  return ans;
}
int cnt[100005], id[100005], rev[100005], premx[100005];
bool chk(int mid) {
  for (int i = 1; i <= n * 2; i++) cnt[i] = 0;
  for (int i = 1; i <= n * 2; i++) id[i] = i;
  sort(id + 1, id + n * 2 + 1,
       [&](int x, int y) { return getval(0, x) < getval(0, y); });
  for (int i = 1; i <= n * 2; i++) rev[id[i]] = i;
  premx[1] = id[1];
  for (int i = 2; i <= n * 2; i++) {
    if (getval(mid, premx[i - 1]) > getval(mid, id[i]))
      premx[i] = premx[i - 1];
    else
      premx[i] = id[i];
  }
  for (int i = n * 2 - 1; i >= 1; i--)
    if (b[id[i]] == b[id[i + 1]]) premx[i] = premx[i + 1];
  for (int i = 1; i <= n; i++) cnt[premx[rev[i]]]++;
  for (int i = 1; i <= n * 2; i++) id[i] = i;
  sort(id + 1, id + n * 2 + 1,
       [&](int x, int y) { return getval(mid, x) > getval(mid, y); });
  int cur = 0;
  for (int i = 1; i <= n * 2; i++) {
    cur += cnt[id[i]];
    if (id[i] > n) cur--;
    while (i < n * 2 && getval(mid, id[i]) == getval(mid, id[i + 1])) {
      i++;
      cur += cnt[id[i]];
      if (id[i] > n) cur--;
    }
    if (cur < 0) return 0;
  }
  return 1;
}
};  // namespace Flow
namespace COST_FLOW {
atcoder::mcf_graph<int, int> G(9 * 4000 + 5);
void add(int u, int v, int w, int c) { G.add_edge(u, v, c, w); }
int get(int mid) {
  int s = n * 9 + 1, t = s + 1;
  for (int i = 1; i <= n; i++) add(s, i, 0, 1);
  for (int i = 1; i <= n * 2; i++) id[i] = i;
  sort(id + 1, id + n * 2 + 1,
       [&](int x, int y) { return getval(0, x) > getval(0, y); });
  for (int i = 1; i <= n * 2; i++) add(i, i + n * 2, 1, 1);
  for (int i = 1; i < n * 2; i++)
    add(id[i] + n * 2, id[i + 1] + n * 2, 0, 0x3f3f3f3f);
  for (int i = 1; i <= n * 2; i++) {
    int j = i;
    while (getval(0, id[i]) == getval(0, id[j + 1])) j++;
    if (j != i) add(id[j] + n * 2, id[i] + n * 2, 0, 0x3f3f3f3f), i = j;
  }
  for (int i = 1; i <= n * 2; i++) add(i, i + n * 4, 0, 0x3f3f3f3f);
  for (int i = 1; i <= n * 2; i++) add(i + n * 2, i + n * 4, 0, 0x3f3f3f3f);
  sort(id + 1, id + n * 2 + 1,
       [&](int x, int y) { return getval(mid, x) > getval(mid, y); });
  for (int i = 1; i <= n * 2; i++) add(i + n * 4, i + n * 6, 1, 0x3f3f3f3f);
  for (int i = 1; i < n * 2; i++)
    add(n * 6 + id[i], n * 6 + id[i + 1], 0, 0x3f3f3f3f);
  for (int i = 1; i <= n * 2; i++) {
    int j = i;
    while (getval(mid, id[i]) == getval(mid, id[j + 1])) j++;
    if (j != i) add(n * 6 + id[j], n * 6 + id[i], 0, 0x3f3f3f3f), i = j;
  }
  for (int i = n + 1; i <= n + n; i++) add(i + n * 4, i + n * 7, 0, 1);
  for (int i = n + 1; i <= n + n; i++) add(i + n * 6, i + n * 7, 0, 1);
  for (int i = n + 1; i <= n + n; i++) add(i + n * 7, t, 0, 1);
  int ans = G.flow(s, t, n).second;
  return ans;
}
};  // namespace COST_FLOW
signed main() {
  cin >> n;
  for (int i = 1; i <= n * 2; i++) a[i] = read(), b[i] = read();
  int l = 0, r = 1e9, ans = -1;
  while (l <= r) {
    int mid = (l + r) / 2;
    if (Flow::chk(mid))
      r = mid - 1, ans = mid;
    else
      l = mid + 1;
  }
  if (ans == -1) return cout << "-1\n", 0;
  cout << ans << " ";
  cout << COST_FLOW::get(ans) << endl;
  return 0;
}