#include <bits/stdc++.h>
using namespace std;
struct arr1 {
  int x1, y1, x2, y2;
} a[1100000];
struct arr2 {
  int x, y1, y2, z;
} c[1100000];
struct tree {
  int a, s, x;
} t[1100000 << 2];
int b[1100000], d[1100000], q[1100000], m;
int read() {
  int v = 0, f = 1;
  char c = getchar();
  while (c < 48 || 57 < c) {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (48 <= c && c <= 57) v = (v << 3) + v + v + c - 48, c = getchar();
  return v * f;
}
void swap(int &x, int &y) {
  int t = x;
  x = y;
  y = t;
}
int hash1(int x) {
  int l = 1;
  int r = m;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (b[mid] == x) return d[mid];
    if (b[mid] < x)
      l = mid + 1;
    else
      r = mid - 1;
  }
}
bool cmp(arr2 a, arr2 b) { return a.x < b.x; }
void pushdown(int p) {
  int l = p << 1;
  int r = l + 1;
  if (!t[p].a) return;
  t[l].s = t[l].s + t[p].a;
  t[l].a = t[l].a + t[p].a;
  t[r].s = t[r].s + t[p].a;
  t[r].a = t[r].a + t[p].a;
  t[p].a = 0;
}
void pushup(int p) {
  if (t[p << 1].s < t[p + p + 1].s) {
    t[p].s = t[p + p + 1].s;
    t[p].x = t[p + p + 1].x;
  } else {
    t[p].s = t[p << 1].s;
    t[p].x = t[p << 1].x;
  }
}
void build(int l, int r, int p) {
  if (l > r) return;
  t[p].a = 0;
  t[p].x = l;
  if (l == r) return;
  int mid = (l + r) >> 1;
  build(l, mid, p << 1);
  build(mid + 1, r, p << 1 | 1);
}
int query(int l, int r, int x, int y, int p) {
  if (x <= l && r <= y) return t[p].s;
  pushdown(p);
  int mid = (l + r) >> 1;
  int ret = -1;
  if (x <= mid) ret = query(l, mid, x, y, p << 1);
  if (y > mid) {
    int t = query(mid + 1, r, x, y, p << 1 | 1);
    if (t > ret) ret = t;
  }
  return ret;
}
void update(int l, int r, int x, int y, int v, int p) {
  if (x <= l && r <= y) {
    t[p].s += v;
    t[p].a += v;
    return;
  }
  pushdown(p);
  int mid = (l + r) >> 1;
  if (x <= mid) update(l, mid, x, y, v, p << 1);
  if (y > mid) update(mid + 1, r, x, y, v, p << 1 | 1);
  pushup(p);
}
int main() {
  int x;
  scanf("%d", &x);
  int k1 = x;
  m = 0;
  int n = 0;
  for (int i = 1; i <= x; i++) {
    scanf("%d%d%d%d", &a[i].x1, &a[i].y1, &a[i].x2, &a[i].y2);
    b[++m] = a[i].x1;
    b[++m] = a[i].y1;
    b[++m] = a[i].x2;
    b[++m] = a[i].y2;
  }
  sort(b + 1, b + m + 1);
  d[1] = 1;
  for (int i = 2; i <= m; i++)
    if (b[i] == b[i - 1])
      d[i] = d[i - 1];
    else
      d[i] = d[i - 1] + 1;
  q[1] = b[1];
  int len = 1;
  for (int i = 2; i <= m; i++)
    if (b[i] != b[i - 1]) q[++len] = b[i];
  for (int i = 1; i <= x; i++) {
    c[++n].x = hash1(a[i].x1);
    c[n].y1 = hash1(a[i].y1);
    c[n].y2 = hash1(a[i].y2);
    c[n].z = 1;
    c[++n].x = hash1(a[i].x2) + 1;
    c[n].y1 = hash1(a[i].y1);
    c[n].y2 = hash1(a[i].y2);
    c[n].z = -1;
  }
  sort(c + 1, c + n + 1, cmp);
  int line = 0;
  int row = 0;
  for (int i = 1; i <= n; i++) {
    line = max(line, c[i].x);
    row = max(row, c[i].y2);
  }
  build(1, row, 1);
  int j = 1;
  for (int i = 1; i <= line; i++) {
    while (j <= n && c[j].x == i) {
      update(1, row, c[j].y1, c[j].y2, c[j].z, 1);
      j++;
    }
    int k = query(1, row, 1, row, 1);
    if (k >= k1 - 1) {
      int p = t[1].x;
      int x = q[i];
      int y = q[p];
      printf("%d %d\n", x, y);
      return 0;
    }
  }
  return 0;
}
