#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 210005;
int H, W, K, Q;
pair<int, int> loc[MAX_N];
pair<pair<int, int>, pair<int, int> > queries[MAX_N];
int fail[MAX_N];
vector<int> xBucket[MAX_N];
vector<int> qxBucket[MAX_N];
vector<int> yBucket[MAX_N];
vector<int> qyBucket[MAX_N];
int tree[4 * MAX_N];
void reset(void);
int query(int node, int start, int end, int startRange, int endRange);
void update(int node, int start, int end, int target, int newVal);
int main() {
  scanf("%d %d %d %d", &W, &H, &K, &Q);
  for (int i = 0; i < K; i++) {
    scanf("%d %d", &loc[i].first, &loc[i].second);
    xBucket[loc[i].first].push_back(loc[i].second);
    yBucket[loc[i].second].push_back(loc[i].first);
  }
  for (int i = 0; i < Q; i++) {
    scanf("%d %d %d %d", &queries[i].first.first, &queries[i].first.second,
          &queries[i].second.first, &queries[i].second.second);
    qxBucket[queries[i].first.first].push_back(i);
    qyBucket[queries[i].first.second].push_back(i);
  }
  reset();
  ;
  for (int i = W; i >= 0; i--) {
    ;
    for (int j = 0; j < xBucket[i].size(); j++) {
      update(0, 0, H + 5, xBucket[i][j], i);
      ;
    }
    for (int j = 0; j < qxBucket[i].size(); j++) {
      int ind = qxBucket[i][j];
      int q = query(0, 0, H + 5, queries[ind].first.second,
                    queries[ind].second.second + 1);
      ;
      if (q <= queries[ind].second.first) {
        fail[ind]++;
      }
    }
  }
  reset();
  ;
  for (int i = H; i >= 0; i--) {
    ;
    for (int j = 0; j < yBucket[i].size(); j++) {
      ;
      update(0, 0, W + 5, yBucket[i][j], i);
    }
    for (int j = 0; j < qyBucket[i].size(); j++) {
      int ind = qyBucket[i][j];
      int q = query(0, 0, W + 5, queries[ind].first.first,
                    queries[ind].second.first + 1);
      ;
      if (q <= queries[ind].second.second) {
        fail[ind]++;
      }
    }
  }
  for (int i = 0; i < Q; i++) {
    if (fail[i] > 0) {
      printf("YES\n");
    } else {
      printf("NO\n");
    }
  }
  return 0;
}
void reset(void) {
  for (int i = 0; i < 4 * MAX_N; i++) {
    tree[i] = MAX_N;
  }
}
int query(int node, int start, int end, int startRange, int endRange) {
  int ans;
  if (end - start <= 1 || (start == startRange && end == endRange)) {
    ans = tree[node];
  } else {
    int mid = (start + end) / 2;
    if (endRange <= mid) {
      ans = query(2 * node + 1, start, mid, startRange, endRange);
    } else if (startRange >= mid) {
      ans = query(2 * node + 2, mid, end, startRange, endRange);
    } else {
      ans = max(query(2 * node + 1, start, mid, startRange, mid),
                query(2 * node + 2, mid, end, mid, endRange));
    }
  }
  return ans;
}
void update(int node, int start, int end, int target, int newVal) {
  if (end - start <= 1) {
    tree[node] = newVal;
  } else {
    int mid = (start + end) / 2;
    if (target < mid) {
      update(2 * node + 1, start, mid, target, newVal);
    } else {
      update(2 * node + 2, mid, end, target, newVal);
    }
    tree[node] = max(tree[2 * node + 1], tree[2 * node + 2]);
  }
}
