#include <bits/stdc++.h>
using namespace std;
template <class T>
inline void read(T &x) {
  int f = 1;
  char k = getchar();
  x = 0;
  for (; k > '9' || k < '0'; k = getchar())
    if (k == '-') f = -1;
  for (; k >= '0' && k <= '9'; k = getchar()) x = (x << 3) + (x << 1) + k - '0';
  x *= f;
}
template <class T>
inline void _print(T x) {
  if (x / 10) _print(x / 10);
  putchar(x % 10 + '0');
}
template <class T>
inline void print(T x) {
  if (x < 0) putchar('-'), x = -x;
  _print(x);
}
long long mul(long long a, long long b, long long mod) {
  long double c = 1.;
  return (a * b - (long long)(c * a * b / mod) * mod) % mod;
}
inline int qpow(int x, int m, int mod) {
  int res = 1, bas = x;
  while (m) {
    if (m & 1) res = (1ll * res * bas) % mod;
    bas = (1ll * bas * bas) % mod, m >>= 1;
  }
  return res;
}
const int N = 1e5 + 5;
int n, a, b, c, d, num, s[N << 2], sz;
struct Node {
  int sa, ea, sb, eb;
} node[N];
inline bool cmp1(Node x, Node y) {
  return x.sa == y.sa ? x.ea < y.ea : x.sa < y.sa;
}
inline bool cmp2(Node x, Node y) {
  return x.sb == y.sb ? x.eb < y.eb : x.sb < y.sb;
}
int T[N << 2], T1[N << 2];
inline void Updata(int pos, int k) {
  for (; pos <= sz; pos += (pos & (-pos))) T[pos] += k;
}
inline int Query(int pos) {
  int res = 0;
  for (; pos; pos -= (pos & (-pos))) res += T[pos];
  return res;
}
inline void Updata1(int pos, int k) {
  for (; pos <= sz; pos += (pos & (-pos))) T1[pos] += k;
}
inline int Query1(int pos) {
  int res = 0;
  for (; pos; pos -= (pos & (-pos))) res += T1[pos];
  return res;
}
inline int get_id(int a) { return lower_bound(s + 1, s + 1 + sz, a) - s; }
multiset<pair<int, int> > S;
int main() {
  read(n);
  for (register int i = 1; i <= n; ++i) {
    read(a), read(b), read(c), read(d);
    node[i] = (Node){a, b, c, d};
    s[++sz] = c, s[++sz] = d, s[++sz] = c - 1;
  }
  sort(node + 1, node + 1 + n, cmp1);
  sort(s + 1, s + 1 + sz), sz = unique(s + 1, s + 1 + sz) - s - 1;
  Updata(get_id(node[1].eb), 1), Updata1(get_id(node[1].sb), 1);
  S.insert(make_pair(node[1].ea, 1));
  for (register int i = 2; i <= n; ++i) {
    while (S.size()) {
      int pos = (*S.begin()).second;
      if (node[pos].ea < node[i].sa) {
        Updata(get_id(node[pos].eb), -1);
        Updata1(get_id(node[pos].sb), -1);
        S.erase(S.begin());
      } else
        break;
    }
    if (S.size()) {
      int res = Query1(get_id(node[i].eb)) - Query(get_id(node[i].sb - 1));
      if (res != (int)S.size()) return puts("NO"), 0;
    }
    Updata(get_id(node[i].eb), 1), Updata1(get_id(node[i].sb), 1);
    S.insert(make_pair(node[i].ea, i));
  }
  memset(T, 0, sizeof(T)), memset(T1, 0, sizeof(T1)), S.clear();
  sort(node + 1, node + 1 + n, cmp2), sz = 0;
  for (register int i = 1; i <= n; ++i)
    s[++sz] = node[i].sa, s[++sz] = node[i].ea, s[++sz] = node[i].sa - 1;
  sort(s + 1, s + 1 + sz), sz = unique(s + 1, s + 1 + sz) - s - 1;
  Updata(get_id(node[1].ea), 1), Updata1(get_id(node[1].sa), 1);
  S.insert(make_pair(node[1].eb, 1));
  for (register int i = 2; i <= n; ++i) {
    while (S.size()) {
      int pos = (*S.begin()).second;
      if (node[pos].eb < node[i].sb) {
        Updata(get_id(node[pos].ea), -1);
        Updata1(get_id(node[pos].sa), -1);
        S.erase(S.begin());
      } else
        break;
    }
    if (S.size()) {
      int res = Query1(get_id(node[i].ea)) - Query(get_id(node[i].sa - 1));
      if (res != (int)S.size()) return puts("NO"), 0;
    }
    Updata(get_id(node[i].ea), 1), Updata1(get_id(node[i].sa), 1);
    S.insert(make_pair(node[i].eb, i));
  }
  puts("YES");
  return 0;
}
