#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
const long double EPS = 1e-8;
const long double PI = 3.14159265358979323;
const int M = 1e9;
const int MAXN = 2 * 1e5;
const int MAX_MEM = 1e8;
int mpos = 0;
char mem[MAX_MEM];
inline void *operator new(size_t n) {
  assert((mpos += n) <= MAX_MEM);
  return (void *)(mem + mpos - n);
}
inline void operator delete(void *) noexcept {}
struct Node {
  int val = -1;
};
struct ST {
  int sz = 2;
  vector<Node> tree;
  ST(int n) {
    while (sz < n) sz <<= 1;
    tree.resize(sz << 1, Node());
  }
  void recalc(int v) {
    tree[v].val = min(tree[v * 2].val, tree[v * 2 + 1].val);
  }
  void update(int v, int l, int r, int pos, int x) {
    if (r - l == 1 && l == pos) {
      tree[v].val = x;
      return;
    }
    int m = (l + r) / 2;
    if (pos < m)
      update(v * 2, l, m, pos, x);
    else
      update(v * 2 + 1, m, r, pos, x);
    recalc(v);
  }
  int get_func(int v, int l, int r, int L, int R) {
    if (R <= l || r <= L) return INF;
    if (L <= l && r <= R) return tree[v].val;
    int m = (l + r) / 2;
    return min(get_func(v * 2, l, m, L, R), get_func(v * 2 + 1, m, r, L, R));
  }
};
struct ST2 {
  int sz = 2;
  vector<Node> tree;
  ST2(int n) {
    while (sz < n) sz <<= 1;
    tree.resize(sz << 1, Node());
  }
  void recalc(int v) {
    tree[v].val = min(tree[v * 2].val, tree[v * 2 + 1].val);
  }
  void update(int v, int l, int r, int pos, int x) {
    if (r - l == 1 && l == pos) {
      tree[v].val = x;
      return;
    }
    int m = (l + r) / 2;
    if (pos < m)
      update(v * 2, l, m, pos, x);
    else
      update(v * 2 + 1, m, r, pos, x);
    recalc(v);
  }
  int get_func(int v, int l, int r, int L, int R) {
    if (R <= l || r <= L) return INF;
    if (L <= l && r <= R) return tree[v].val;
    int m = (l + r) / 2;
    return min(get_func(v * 2, l, m, L, R), get_func(v * 2 + 1, m, r, L, R));
  }
};
struct point {
  int x, y;
};
struct query {
  point a, b;
  int type, num;
};
bool cmp1(query f, query s) {
  if (f.a.x == s.a.x)
    if (f.a.y == s.a.y)
      return f.type < s.type;
    else
      return f.a.y < s.a.y;
  else
    return f.a.x < s.a.x;
}
bool cmp2(query f, query s) {
  if (f.a.y == s.a.y)
    if (f.a.x == s.a.x)
      return f.type < s.type;
    else
      return f.a.x < s.a.x;
  else
    return f.a.y < s.a.y;
}
vector<query> q, p;
int n, m, k, qq;
vector<bool> ans;
signed main() {
  {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
  };
  cin >> n >> m >> k >> qq;
  q.resize(k + qq);
  p.resize(k + qq);
  ans.resize(qq);
  for (int i = 0; i < k; i++) {
    int a, b;
    cin >> a >> b;
    q[i].a.x = p[i].a.x = a;
    q[i].a.y = p[i].a.y = b;
    q[i].type = p[i].type = 1;
  }
  int j = k;
  for (int i = 0; i < qq; i++) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    q[j].a.x = p[j].a.x = c;
    q[j].b.x = p[j].b.x = a;
    q[j].a.y = p[j].a.y = d;
    q[j].b.y = p[j].b.y = b;
    q[j].type = p[j].type = 2;
    q[j].num = p[j].num = i;
    j++;
  }
  sort(q.begin(), q.end(), cmp1);
  sort(p.begin(), p.end(), cmp2);
  ST tmp(m);
  for (int i = 0; i < q.size(); i++) {
    if (q[i].type == 1) {
      tmp.update(1, 0, m, q[i].a.y - 1, q[i].a.x);
    } else if (q[i].type == 2) {
      if (tmp.get_func(1, 0, m, q[i].b.y - 1, q[i].a.y) >= q[i].b.x)
        ans[q[i].num] = 1;
      else
        ans[q[i].num] = 0;
    }
  }
  ST2 tmp2(n);
  for (int i = 0; i < p.size(); i++) {
    if (p[i].type == 1) {
      tmp2.update(1, 0, n, p[i].a.x - 1, p[i].a.y);
    } else if (p[i].type == 2) {
      if (tmp2.get_func(1, 0, n, p[i].b.x - 1, p[i].a.x) >= p[i].b.y)
        ans[p[i].num] = 1;
      else
        ans[p[i].num] = ans[p[i].num] | 0;
    }
  }
  for (int i = 0; i < qq; i++)
    if (ans[i] == 1)
      cout << "YES" << '\n';
    else
      cout << "NO" << '\n';
  return 0;
}
