#include <bits/stdc++.h>
using namespace std;
int n, m, k, q;
struct Chess {
  int x, y;
} chess[500100];
inline bool comp1(const Chess a, const Chess b) { return a.x < b.x; }
inline bool comp3(const Chess a, const Chess b) { return a.y < b.y; }
struct Matrix {
  int x1, y1;
  int x2, y2;
  int id;
  bool rowok, colok;
} ma[500100];
inline bool comp2(const Matrix a, const Matrix b) { return a.x2 < b.x2; }
inline bool comp4(const Matrix a, const Matrix b) { return a.y2 < b.y2; }
inline bool comp5(const Matrix a, const Matrix b) { return a.id < b.id; }
struct Segment_Tree {
  int left, right;
  int min;
} tree[500100 << 2];
inline void plant_tree(int id, int l, int r) {
  tree[id].left = l, tree[id].right = r;
  tree[id].min = 0;
  if (l == r) return;
  int mid = (l + r) >> 1;
  plant_tree(id << 1, l, mid);
  plant_tree(id << 1 | 1, mid + 1, r);
}
inline void update_seed(int id, int p, int v) {
  if (tree[id].left == p && p == tree[id].right) {
    tree[id].min = max(tree[id].min, v);
    return;
  }
  int mid = (tree[id].left + tree[id].right) >> 1;
  if (p <= mid)
    update_seed(id << 1, p, v);
  else
    update_seed(id << 1 | 1, p, v);
  tree[id].min = min(tree[id << 1].min, tree[id << 1 | 1].min);
}
inline int query_min(int id, int l, int r) {
  if (tree[id].left == l && tree[id].right == r) {
    return tree[id].min;
  }
  int mid = (tree[id].left + tree[id].right) >> 1;
  if (r <= mid)
    return query_min(id << 1, l, r);
  else if (mid < l)
    return query_min(id << 1 | 1, l, r);
  else
    return min(query_min(id << 1, l, mid), query_min(id << 1 | 1, mid + 1, r));
}
int main() {
  scanf("%d%d%d%d", &n, &m, &k, &q);
  for (int i = 1; i <= k; i++) {
    scanf("%d%d", &chess[i].x, &chess[i].y);
    if (chess[i].x < 1 || chess[i].x > n || chess[i].y < 1 || chess[i].y > m)
      while (1)
        ;
  }
  for (int i = 1; i <= q; i++) {
    scanf("%d%d%d%d", &ma[i].x1, &ma[i].y1, &ma[i].x2, &ma[i].y2);
    if (ma[i].x1 > ma[i].x2 || ma[i].y1 > ma[i].y2)
      while (1)
        ;
    if (ma[i].x1 < 1 || ma[i].x1 > n || ma[i].x2 < 1 || ma[i].x2 > n)
      while (1)
        ;
    if (ma[i].y1 < 1 || ma[i].y1 > m || ma[i].y2 < 1 || ma[i].y2 > m)
      while (1)
        ;
    ma[i].id = i;
  }
  sort(chess + 1, chess + 1 + k, comp1);
  sort(ma + 1, ma + 1 + q, comp2);
  int t1 = 1, t2 = 1;
  plant_tree(1, 1, m);
  while (t1 <= q) {
    while (t2 <= k && chess[t2].x <= ma[t1].x2) {
      update_seed(1, chess[t2].y, chess[t2].x);
      t2++;
    }
    int nowx2 = ma[t1].x2;
    while (t1 <= q && ma[t1].x2 == nowx2) {
      int mini = query_min(1, ma[t1].y1, ma[t1].y2);
      if (mini >= ma[t1].x1)
        ma[t1].rowok = true;
      else
        ma[t1].rowok = false;
      t1++;
    }
  }
  sort(chess + 1, chess + 1 + k, comp3);
  sort(ma + 1, ma + 1 + q, comp4);
  t1 = 1, t2 = 1;
  plant_tree(1, 1, n);
  while (t1 <= q) {
    while (t2 <= k && chess[t2].y <= ma[t1].y2) {
      update_seed(1, chess[t2].x, chess[t2].y);
      t2++;
    }
    int nowy2 = ma[t1].y2;
    while (t1 <= q && ma[t1].y2 == nowy2) {
      int mini = query_min(1, ma[t1].x1, ma[t1].x2);
      if (mini >= ma[t1].y1)
        ma[t1].colok = true;
      else
        ma[t1].colok = false;
      t1++;
    }
  }
  sort(ma + 1, ma + 1 + q, comp5);
  bool ok = true;
  for (int i = 1; i <= q; i++) {
    if (!ma[i].rowok && !ma[i].colok)
      ok = false;
    else
      ok = true;
    printf("%s\n", ok ? "YES" : "NO");
  }
  return 0;
}
