import java.io.*;
import java.util.*;

/**
* @author master_j
* @version 0.4.1
* @since Mar 22, 2015
*/
public class Solution {
    private void solve() throws IOException {
        int w = io.nI(), h = io.nI(), rooksNum = io.nI(), rectsNum = io.nI();

        Rook[] rooks = new Rook[rooksNum];
        for (int i = 0; i < rooks.length; i++)
            rooks[i] = new Rook(io);

        Rect[] rects = new Rect[rectsNum];
        for (int i = 0; i < rects.length; i++)
            rects[i] = new Rect(io, i);

        boolean[] ans = new boolean[rectsNum];
        int rookPtr, rectPtr;

        Arrays.sort(rooks, Rook.lrComp);
        Arrays.sort(rects, Rect.lrComp);
//        SegmentTreeMinS stLR = new SegmentTreeMinS(1 + 1 + h);
        SegmentTreeMinD stLR = new SegmentTreeMinD(1 + 1 + h);
        rookPtr = 0;
        rectPtr = 0;
        while (true) {
            Rook rook = null;
            if (rookPtr < rooks.length)
                rook = rooks[rookPtr];

            Rect rect = null;
            if (rectPtr < rects.length)
                rect = rects[rectPtr];

            if (rect == null)
                break;

            if (rook != null && rook.x <= rect.x1) {
                stLR.update(rook.y, rook.x);
                rookPtr++;
            } else {
                if (rect.x0 <= stLR.min(rect.y0, rect.y1))
                    ans[rect.id] = true;
                rectPtr++;
            }
        }

        Arrays.sort(rooks, Rook.btComp);
        Arrays.sort(rects, Rect.btComp);
        //SegmentTreeMinS stBT = new SegmentTreeMinS(1 + 1 + w);
        SegmentTreeMinD stBT = new SegmentTreeMinD(1 + 1 + w);
        rookPtr = 0;
        rectPtr = 0;
        while (true) {
            Rook rook = null;
            if (rookPtr < rooks.length)
                rook = rooks[rookPtr];

            Rect rect = null;
            if (rectPtr < rects.length)
                rect = rects[rectPtr];

            if (rect == null)
                break;

            if (rook != null && rook.y <= rect.y1) {
                stBT.update(rook.x, rook.y);
                rookPtr++;
            } else {
                if (rect.y0 <= stBT.min(rect.x0, rect.x1))
                    ans[rect.id] = true;
                rectPtr++;
            }
        }

        for (boolean b : ans)
            io.wln(b ? "YES" : "NO");
    }//2.2250738585072012e-308

    public static void main(String[] args) throws IOException {
        IO.launchSolution(args);
    }

    Solution(IO io) throws IOException {
        this.io = io;
        solve();
    }

    private final IO io;
}

class IO {
    static final String _localArg = "master_j";
    private static final String _problemName = "";
    private static final IO.Mode _inMode = Mode.STD_;
    private static final IO.Mode _outMode = Mode.STD_;
    private static final boolean _autoFlush = false;

    static enum Mode {STD_, _PUT_TXT, PROBNAME_}

    private final StreamTokenizer st;
    private final BufferedReader br;
    private final Reader reader;

    private final PrintWriter pw;
    private final Writer writer;

    static void launchSolution(String[] args) throws IOException {
        boolean local = (args.length == 1 && args[0].equals(IO._localArg));
        IO io = new IO(local);

        long nanoTime = 0;
        if (local) {
            nanoTime -= System.nanoTime();
            io.wln("<output>");
        }

        io.flush();
        new Solution(io);
        io.flush();

        if (local) {
            io.wln("</output>");
            nanoTime += System.nanoTime();
            final long D9 = 1000000000, D6 = 1000000, D3 = 1000;
            if (nanoTime >= D9)
                io.wf("%d.%d seconds\n", nanoTime / D9, nanoTime % D9);
            else if (nanoTime >= D6)
                io.wf("%d.%d millis\n", nanoTime / D6, nanoTime % D6);
            else if (nanoTime >= D3)
                io.wf("%d.%d micros\n", nanoTime / D3, nanoTime % D3);
            else
                io.wf("%d nanos\n", nanoTime);
        }

        io.close();
    }

    IO(boolean local) throws IOException {
        if (_inMode == Mode.PROBNAME_ || _outMode == Mode.PROBNAME_)
            if (_problemName.length() == 0)
                throw new IllegalStateException("You imbecile. Where's my <_problemName>?");

        if (_problemName.length() > 0)
            if (_inMode != Mode.PROBNAME_ && _outMode != Mode.PROBNAME_)
                throw new IllegalStateException("You imbecile. What's the <_problemName> for?");

        Locale.setDefault(Locale.US);

        if (local) {
            reader = new FileReader("input.txt");
            writer = new OutputStreamWriter(System.out);
        } else {
            switch (_inMode) {
                case STD_:
                    reader = new InputStreamReader(System.in);
                    break;
                case PROBNAME_:
                    reader = new FileReader(_problemName + ".in");
                    break;
                case _PUT_TXT:
                    reader = new FileReader("input.txt");
                    break;
                default:
                    throw new NullPointerException("You imbecile. Gimme _inMode.");
            }
            switch (_outMode) {
                case STD_:
                    writer = new OutputStreamWriter(System.out);
                    break;
                case PROBNAME_:
                    writer = new FileWriter(_problemName + ".out");
                    break;
                case _PUT_TXT:
                    writer = new FileWriter("output.txt");
                    break;
                default:
                    throw new NullPointerException("You imbecile. Gimme _outMode.");
            }
        }

        br = new BufferedReader(reader);
        st = new StreamTokenizer(br);

        pw = new PrintWriter(writer, _autoFlush);

        if (local && _autoFlush)
            wln("Note: auto-flush is on.");
    }

    void wln()          {pw.println(); }
    void wln(boolean x) {pw.println(x);}
    void wln(char x)    {pw.println(x);}
    void wln(char x[])  {pw.println(x);}
    void wln(double x)  {pw.println(x);}
    void wln(float x)   {pw.println(x);}
    void wln(int x)     {pw.println(x);}
    void wln(long x)    {pw.println(x);}
    void wln(Object x)  {pw.println(x);}
    void wln(String x)  {pw.println(x);}

    void wf(String f, Object...o){pw.printf(f, o);}

    void w(boolean x)   {pw.print(x);}
    void w(char x)      {pw.print(x);}
    void w(char x[])    {pw.print(x);}
    void w(double x)    {pw.print(x);}
    void w(float x)     {pw.print(x);}
    void w(int x)       {pw.print(x);}
    void w(long x)      {pw.print(x);}
    void w(Object x)    {pw.print(x);}
    void w(String x)    {pw.print(x);}

    int nI() throws IOException    {st.nextToken(); return (int)st.nval;}
    double nD() throws IOException {st.nextToken(); return st.nval;}
    float nF() throws IOException  {st.nextToken(); return (float)st.nval;}
    long nL() throws IOException   {st.nextToken(); return (long)st.nval;}
    String nS() throws IOException {st.nextToken(); return st.sval;}

    int[] nIa(int n) throws IOException {
        int[] a = new int[n];
        for (int i = 0; i < n; i++)
            a[i] = nI();
        return a;
    }
    double[] nDa(int n) throws IOException {
        double[] a = new double[n];
        for (int i = 0; i < n; i++)
            a[i] = nD();
        return a;
    }
    String[] nSa(int n) throws IOException {
        String[] a = new String[n];
        for (int i = 0; i < n; i++)
            a[i] = nS();
        return a;
    }

    void wc(String x)         {wc(x.toCharArray());}
    void wc(char c1, char c2) {for (char c = c1; c<=c2; c++) wc(c);}
    void wc(char x[])         {for (char c : x) wc(c); }
    void wc(char x)           {st.ordinaryChar(x); st.wordChars(x, x);}

    public boolean eof() {return st.ttype == StreamTokenizer.TT_EOF;}
    public boolean eol() {return st.ttype == StreamTokenizer.TT_EOL;}

    void flush() {pw.flush();}
    void close() throws IOException {reader.close(); br.close(); flush(); pw.close();}
}

class SegmentTreeMinS {
    private final int n;
    private final int[] tree;

    SegmentTreeMinS(int n) {
        this.n = n;
        this.tree = new int[4 * n];
        Arrays.fill(tree, -1);
    }

    int min(int l, int r) {
        return min(1, 0, n - 1, l, r);
    }

    private int min(int v, int tl, int tr, int l, int r) {
        if (l > r)
            return Integer.MAX_VALUE;
        if (l == tl && r == tr)
            return tree[v];
        int tm = (tl + tr) / 2;
        return Math.min(min(2 * v, tl, tm, l, Math.min(tm, r)),
                min(1 + 2 * v, 1 + tm, tr, Math.max(l, 1 + tm), r));
    }

    void update(int i, int val) {
        update(1, i, val, 0, n - 1);
    }

    private void update(int v, int i, int val, int tl, int tr) {
        if (i < tl || tr < i)
            return;
        if (tl == tr) {
            tree[v] = val;
            return;
        }

        int tm = (tl + tr) / 2;
        update(2 * v, i, val, tl, tm);
        update(1 + 2 * v, i, val, 1 + tm, tr);
        tree[v] = Math.min(tree[2 * v], tree[1 + 2 * v]);
    }
}

class SegmentTreeMinD {
    private final SegmentTreeMinD left, right;
    private final int l, r;
    private int val;

    SegmentTreeMinD(int n) {
        this.l = 0;
        this.r = n - 1;
        this.val = -1;
        this.left = new SegmentTreeMinD(0, r / 2);
        this.right = new SegmentTreeMinD(1 + r / 2, r);
    }

    private SegmentTreeMinD(int l, int r) {
        this.l = l;
        this.r = r;
        this.val = -1;

        if (l == r) {
            this.left = null;
            this.right = null;
        } else {
            int m = (l + r) / 2;
            this.left = new SegmentTreeMinD(l, m);
            this.right = new SegmentTreeMinD(1 + m, r);
        }
    }

    void update(int i, int val) {
        if (i < l || r < i)
            return;
        if (l == r) {
            this.val = val;
            return;
        }
        left.update(i, val);
        right.update(i, val);
        this.val = Math.min(left.val, right.val);
    }

    int min(int tl, int tr) {
        if (tl > tr)
            return Integer.MAX_VALUE;
        if (l == tl && r == tr)
            return val;
        return Math.min(left.min(tl, Math.min(left.r, tr)),
                right.min(Math.max(right.l, tl), tr));
    }
}

class Rook {
    final int x, y;

    Rook(IO io) throws IOException {
        this.x = io.nI();
        this.y = io.nI();
    }

    static Comparator<Rook> lrComp = new Comparator<Rook>() {
        @Override
        public int compare(Rook r0, Rook r1) {
            return r0.x - r1.x;
        }
    };

    static Comparator<Rook> btComp = new Comparator<Rook>() {
        @Override
        public int compare(Rook r0, Rook r1) {
            return r0.y - r1.y;
        }
    };
}

class Rect {
    final int x0, y0, x1, y1;
    final int id;

    Rect(IO io, int id) throws IOException {
        this.x0 = io.nI();
        this.y0 = io.nI();
        this.x1 = io.nI();
        this.y1 = io.nI();
        this.id = id;
    }

    static Comparator<Rect> lrComp = new Comparator<Rect>() {
        @Override
        public int compare(Rect r0, Rect r1) {
            return r0.x1 - r1.x1;
        }
    };

    static Comparator<Rect> btComp = new Comparator<Rect>() {
        @Override
        public int compare(Rect r0, Rect r1) {
            return r0.y1 - r1.y1;
        }
    };
}


import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import static java.lang.Integer.max;
import static java.lang.Integer.min;
import java.util.ArrayList;
import static java.util.Arrays.sort;
import java.util.Comparator;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.TreeSet;

//<editor-fold defaultstate="collapsed" desc="Main">
public class Main {
    // https://netbeans.org/kb/73/java/editor-codereference_ru.html#display

    private void run() {
        try {
            Locale.setDefault(Locale.US);
        } catch (Exception e) {
        }
        boolean oj = true;
        try {
            oj = System.getProperty("MYLOCAL") == null;
        } catch (Exception e) {
        }

        if (oj) {
            sc = new FastScanner(new InputStreamReader(System.in));
            out = new PrintWriter(new OutputStreamWriter(System.out));
//            try {
//                sc = new FastScanner(new FileReader ("stacks.in" ));
//                out = new PrintWriter(new FileWriter("stacks.out"));
//            } catch (IOException e) {
//                MLE();
//            }
        } else {
            try {
                sc = new FastScanner(new FileReader("input.txt"));
                out = new PrintWriter(new FileWriter("output.txt"));
            } catch (IOException e) {
                MLE();
            }
        }
        Solver s = new Solver();
        s.sc = sc;
        s.out = out;
        s.solve();
        if (!oj) {
            err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
            err.printf("Mem: %d\n", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20);
        }
        out.flush();
    }

    private void show(int[] arr) {
        for (int v : arr) {
            err.print(" " + v);
        }
        err.println();
    }

    public static void exit() {
        err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
        err.printf("Mem: %d\n", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20);
        out.flush();
        out.close();
        System.exit(0);
    }

    public static void MLE() {
        int[][] arr = new int[1024 * 1024][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[1024 * 1024];
        }
    }

    public static void main(String[] args) {
        new Main().run();
    }

    static long timeBegin = System.currentTimeMillis();
    static FastScanner sc;
    static PrintWriter out;
    static PrintStream err = System.err;
}
    //</editor-fold>

//<editor-fold defaultstate="collapsed" desc="FastScanner">
class FastScanner {

    BufferedReader br;
    StringTokenizer st;

    FastScanner(InputStreamReader reader) {
        br = new BufferedReader(reader);
        st = new StringTokenizer("");
    }

    String next() {
        while (!st.hasMoreElements()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception ex) {
                return null;
            }
        }
        return st.nextToken();
    }

    int nextInt() {
        return Integer.parseInt(next());
    }

    long nextLong() {
        return Long.parseLong(next());
    }

    double nextDouble() {
        return Double.parseDouble(next());
    }

    String nextLine() {
        try {
            return br.readLine();
        } catch (IOException ex) {
            return null;
        }
    }
}
//</editor-fold>

class Solver {

    void aser(boolean OK) {
        if (!OK) {
            Main.MLE();
        }
    }

    FastScanner sc;
    PrintWriter out;
    static PrintStream err = System.err;

    class Qwer{
        int x1, y1, x2, y2, id;

        public Qwer(int x1, int y1, int x2, int y2, int id) {
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
            this.id = id;
        }

    }

    class Tree{

        int n;
        int[] tree;

        public Tree(int n) {
            this.n = n;
            tree = new int[4*n];
        }

        void set(int pos, int val){
            set(pos,val, 1,1,n);
        }

        private void set(int pos, int val, int v, int tl, int tr) {
            if(tl == tr){
                aser(pos == tl);
                tree[v] = val;
            } else {
                int tm = (tl + tr) / 2;
                if( pos <= tm ) set(pos, val, 2*v  , tl  , tm);
                else            set(pos, val, 2*v+1, tm+1, tr);
                tree[v] = min(tree[2*v], tree[2*v+1]);
            }
        }

        int get(int l, int r){
            return get(l,r, 1,1,n);
        }

        private int get(int l, int r, int v, int tl, int tr) {
            if(l > r) return Integer.MAX_VALUE;

            if(l==tl && r==tr){
                return tree[v];
            } else {
                int tm = (tl + tr) / 2;
                return min(
                    get(          l, min(r,tm), 2*v  , tl  , tm),
                    get(max(l,tm+1),         r, 2*v+1, tm+1, tr)
                );
            }
        }

    }

    int maxX, maxY, cntL, Q;
    Point[] ps;
    Qwer[] q;
    boolean[] answer;

    void solve() {
        maxX = sc.nextInt();
        maxY = sc.nextInt();
        cntL = sc.nextInt();
        Q    = sc.nextInt();

        ps = new Point[cntL];
        for (int i = 0; i < cntL; i++) {
            ps[i] = new Point(sc.nextInt(), sc.nextInt());
        }

        q = new Qwer[Q];
        for (int i = 0; i < Q; i++) {
            q[i] = new Qwer(sc.nextInt(), sc.nextInt(),
                            sc.nextInt(), sc.nextInt(), i);
        }

        answer = new boolean[Q];
        for (int iter = 0; iter < 2; iter++) {
            sort(ps, new Comparator<Point>(){
                @Override
                public int compare(Point a, Point b) {
                    return Integer.compare(a.x, b.x);
                }
            });
            sort(q, new Comparator<Qwer>() {
                @Override
                public int compare(Qwer a, Qwer b) {
                    return Integer.compare(a.x2, b.x2);
                }
            });
            int posPs = 0, posQ = 0;

            Tree tree = new Tree(max(maxX,maxY)+5);

            for (int x = 1; x <= maxX; x++) {
                for( ;posPs < ps.length && ps[posPs].x == x; ++posPs ){
                    tree.set( ps[posPs].y, ps[posPs].x );
                }
                for( ; posQ < q.length && q[posQ].x2 == x; ++posQ ){
                    int minx = tree.get( q[posQ].y1, q[posQ].y2 );
                    if( q[posQ].x1 <= minx )
                        answer[q[posQ].id] = true;
                }
            }

            int t;
            t = maxX; maxX = maxY; maxY = t;
            for (Point p : ps) {
                t = p.x; p.x = p.y; p.y = t;
            }
            for (Qwer qq : q) {
                t = qq.x1; qq.x1 = qq.y1; qq.y1 = t;
                t = qq.x2; qq.x2 = qq.y2; qq.y2 = t;
            }

        }

        for (boolean b : answer) {
            out.println(b?"YES":"NO");
        }

    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main {
	static BufferedReader reader;
	static StringTokenizer tokenizer;
	static PrintWriter writer;

	static int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	static long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	static double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	static boolean eof = false;

	static String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	public static void main(String[] args) throws IOException {
		tokenizer = null;
		// reader = new BufferedReader(new FileReader("grave.in"));
		// writer = new PrintWriter(new FileWriter("grave.out"));
		reader = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		writer = new PrintWriter(System.out);
		banana();
		reader.close();
		writer.close();
	}

	static class P {
		public int x, y;

		public P(int _x, int _y) {
			this.x = _x;
			this.y = _y;
		}
	}

	static class Rect {
		public int x1, x2, y1, y2, id;

		public Rect(int _x1, int _x2, int _y1, int _y2, int _id) {
			this.x1 = _x1;
			this.x2 = _x2;
			this.y1 = _y1;
			this.y2 = _y2;
			this.id = _id;
		}
	}

	static int tree[];

	static void update(int t, int tl, int tr, int index, int value) {
		if (tree[t] == 0)
			tree[t] = value;
		else
			tree[t] = Math.min(tree[t], value);

		if (tl == tr) {
			tree[t] = value;
			return;
		}

		int tm = (tl + tr) / 2;
		if (index <= tm)
			update(2 * t, tl, tm, index, value);
		else
			update(2 * t + 1, tm + 1, tr, index, value);
	}

	static int inf = 1000000;

	static int getMin(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return inf;

		if (l == tl && r == tr)
			return tree[t];

		int tm = (tl + tr) / 2;
		return Math.min(getMin(2 * t, tl, tm, l, Math.min(tm, r)),
				getMin(2 * t + 1, tm + 1, tr, Math.max(l, tm + 1), r));
	}

	static void banana() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int q = nextInt();

		P a[] = new P[k];
		for (int i = 0; i < k; ++i) {
			a[i] = new P(nextInt(), nextInt());
		}

		boolean ans[] = new boolean[q];
		Rect b[] = new Rect[q];
		for (int i = 0; i < q; ++i) {
			int x1 = nextInt();
			int y1 = nextInt();
			int x2 = nextInt();
			int y2 = nextInt();

			b[i] = new Rect(x1, x2, y1, y2, i);
		}

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.y - b.y;
			}
		});

		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.y2 - b.y2;
			}

		});

		tree = new int[4 * n + 20];
		Arrays.fill(tree, 0);

		int counter = 0;
		int c = 0;
		for (int i = 1; i <= m; ++i) {
			while (counter < k && a[counter].y == i) {
				update(1, 1, n, a[counter].x, i);
				++counter;
			}

			while (c < q && b[c].y2 == i) {
				int val = getMin(1, 1, n, b[c].x1, b[c].x2);
				if (val != inf && val >= b[c].y1)
					ans[b[c].id] = true;

				++c;
			}
		}

		counter = 0;
		c = 0;
		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.x2 - b.x2;
			}
		});

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.x - b.x;
			}
		});

		tree = new int[4 * m + 20];
		Arrays.fill(tree, 0);
		counter = 0;
		c = 0;
		for (int i = 1; i <= n; ++i) {
			while (counter < k && a[counter].x == i) {
				update(1, 1, m, a[counter].y, i);
				++counter;
			}

			while (c < q && b[c].x2 == i) {
				int val = getMin(1, 1, m, b[c].y1, b[c].y2);
				if (val != inf && val >= b[c].x1)
					ans[b[c].id] = true;

				++c;
			}
		}

		for (int i = 0; i < q; ++i) {
			writer.println(ans[i] ? "YES" : "NO");
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main {
	static BufferedReader reader;
	static StringTokenizer tokenizer;
	static PrintWriter writer;

	static int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	static long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	static double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	static boolean eof = false;

	static String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	public static void main(String[] args) throws IOException {
		tokenizer = null;
		// reader = new BufferedReader(new FileReader("grave.in"));
		// writer = new PrintWriter(new FileWriter("grave.out"));
		reader = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		writer = new PrintWriter(System.out);
		banana();
		reader.close();
		writer.close();
	}

	static class P {
		public int x, y;

		public P(int _x, int _y) {
			this.x = _x;
			this.y = _y;
		}
	}

	static class Rect {
		public int x1, x2, y1, y2, id;

		public Rect(int _x1, int _x2, int _y1, int _y2, int _id) {
			this.x1 = _x1;
			this.x2 = _x2;
			this.y1 = _y1;
			this.y2 = _y2;
			this.id = _id;
		}
	}

	static int tree[];

	static void update(int t, int tl, int tr, int index, int value) {
		tree[t] = Math.max(tree[t], value);

		if (tl == tr) {
			tree[t] = value;
			return;
		}

		int tm = (tl + tr) / 2;
		if (index <= tm)
			update(2 * t, tl, tm, index, value);
		else
			update(2 * t + 1, tm + 1, tr, index, value);
	}

	static int inf = 1000000;

	static int getMin(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return inf;

		if (l == tl && r == tr)
			return tree[t];

		int tm = (tl + tr) / 2;
		return Math.min(getMin(2 * t, tl, tm, l, Math.min(tm, r)),
				getMin(2 * t + 1, tm + 1, tr, Math.max(l, tm + 1), r));
	}

	static void banana() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int q = nextInt();

		P a[] = new P[k];
		for (int i = 0; i < k; ++i) {
			a[i] = new P(nextInt(), nextInt());
		}

		boolean ans[] = new boolean[q];
		Rect b[] = new Rect[q];
		for (int i = 0; i < q; ++i) {
			int x1 = nextInt();
			int y1 = nextInt();
			int x2 = nextInt();
			int y2 = nextInt();

			b[i] = new Rect(x1, x2, y1, y2, i);
		}

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.y - b.y;
			}
		});

		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.y2 - b.y2;
			}

		});

		tree = new int[4 * n + 20];
		Arrays.fill(tree, 0);

		int counter = 0;
		int c = 0;
		for (int i = 1; i <= m; ++i) {
			while (counter < k && a[counter].y == i) {
				update(1, 1, n, a[counter].x, i);
				++counter;
			}

			while (c < q && b[c].y2 == i) {
				int val = getMin(1, 1, n, b[c].x1, b[c].x2);
				if (val != inf && val >= b[c].y1)
					ans[b[c].id] = true;

				++c;
			}
		}

		counter = 0;
		c = 0;
		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.x2 - b.x2;
			}
		});

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.x - b.x;
			}
		});

		tree = new int[4 * m + 20];
		Arrays.fill(tree, 0);
		counter = 0;
		c = 0;
		for (int i = 1; i <= n; ++i) {
			while (counter < k && a[counter].x == i) {
				update(1, 1, m, a[counter].y, i);
				++counter;
			}

			while (c < q && b[c].x2 == i) {
				int val = getMin(1, 1, m, b[c].y1, b[c].y2);
				if (val != inf && val >= b[c].x1)
					ans[b[c].id] = true;

				++c;
			}
		}

		for (int i = 0; i < q; ++i) {
			writer.println(ans[i] ? "YES" : "NO");
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main {
	static BufferedReader reader;
	static StringTokenizer tokenizer;
	static PrintWriter writer;

	static int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	static long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	static double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	static boolean eof = false;

	static String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	public static void main(String[] args) throws IOException {
		tokenizer = null;
		// reader = new BufferedReader(new FileReader("grave.in"));
		// writer = new PrintWriter(new FileWriter("grave.out"));
		reader = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		writer = new PrintWriter(System.out);
		banana();
		reader.close();
		writer.close();
	}

	static class P {
		public int x, y;

		public P(int _x, int _y) {
			this.x = _x;
			this.y = _y;
		}
	}

	static class Rect {
		public int x1, x2, y1, y2, id;

		public Rect(int _x1, int _x2, int _y1, int _y2, int _id) {
			this.x1 = _x1;
			this.x2 = _x2;
			this.y1 = _y1;
			this.y2 = _y2;
			this.id = _id;
		}
	}

	static int tree[];
	static int maxTree[];

	static void update(int t, int tl, int tr, int index, int value) {
		tree[t] = Math.min(tree[t], value);
		maxTree[t] = Math.max(maxTree[t], value);

		if (tl == tr) {
			tree[t] = value;
			return;
		}

		int tm = (tl + tr) / 2;
		if (index <= tm)
			update(2 * t, tl, tm, index, value);
		else
			update(2 * t + 1, tm + 1, tr, index, value);
	}

	static int inf = 1000000;

	static int getMax(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return 0;
		if (l == tl && r == tr)
			return maxTree[t];
		int tm = (tl + tr) / 2;
		return Math.max(getMax(2 * t, tl, tm, l, Math.min(r, tm)),
				getMax(2 * t + 1, tm + 1, tr, Math.max(tm + 1, l), r));
	}

	static int getMin(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return inf;

		if (l == tl && r == tr)
			return tree[t];

		int tm = (tl + tr) / 2;
		return Math.min(getMin(2 * t, tl, tm, l, Math.min(tm, r)),
				getMin(2 * t + 1, tm + 1, tr, Math.max(l, tm + 1), r));
	}

	static void banana() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int q = nextInt();

		P a[] = new P[k];
		for (int i = 0; i < k; ++i) {
			a[i] = new P(nextInt(), nextInt());
		}

		boolean ans[] = new boolean[q];
		Rect b[] = new Rect[q];
		for (int i = 0; i < q; ++i) {
			int x1 = nextInt();
			int y1 = nextInt();
			int x2 = nextInt();
			int y2 = nextInt();

			b[i] = new Rect(x1, x2, y1, y2, i);
		}

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.y - b.y;
			}
		});

		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.y2 - b.y2;
			}

		});

		tree = new int[4 * n + 20];
		maxTree = new int[4 * n + 20];
		Arrays.fill(tree, inf);
		Arrays.fill(maxTree, inf);

		int counter = 0;
		int c = 0;
		for (int i = 1; i <= m; ++i) {
			while (counter < k && a[counter].y == i) {
				update(1, 1, n, a[counter].x, i);
				++counter;
			}

			while (c < q && b[c].y2 == i) {
				int val = getMin(1, 1, n, b[c].x1, b[c].x2);
				if (getMax(1, 1, n, b[c].x1, b[c].x2) != inf && val >= b[c].y1)
					ans[b[c].id] = true;

				++c;
			}
		}

		counter = 0;
		c = 0;
		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.x2 - b.x2;
			}
		});

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.x - b.x;
			}
		});

		tree = new int[4 * m + 20];
		maxTree = new int[4 * m + 20];
		Arrays.fill(tree, inf);
		Arrays.fill(maxTree, inf);
		counter = 0;
		c = 0;
		for (int i = 1; i <= n; ++i) {
			while (counter < k && a[counter].x == i) {
				update(1, 1, m, a[counter].y, i);
				++counter;
			}

			while (c < q && b[c].x2 == i) {
				int val = getMin(1, 1, m, b[c].y1, b[c].y2);
				if (val >= b[c].x1 && getMax(1, 1, m, b[c].y1, b[c].y2) != inf)
					ans[b[c].id] = true;

				++c;
			}
		}

		for (int i = 0; i < q; ++i) {
			writer.println(ans[i] ? "YES" : "NO");
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main {
	static BufferedReader reader;
	static StringTokenizer tokenizer;
	static PrintWriter writer;

	static int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	static long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	static double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	static boolean eof = false;

	static String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	public static void main(String[] args) throws IOException {
		tokenizer = null;
		// reader = new BufferedReader(new FileReader("grave.in"));
		// writer = new PrintWriter(new FileWriter("grave.out"));
		reader = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		writer = new PrintWriter(System.out);
		banana();
		reader.close();
		writer.close();
	}

	static class P {
		public int x, y;

		public P(int _x, int _y) {
			this.x = _x;
			this.y = _y;
		}
	}

	static class Rect {
		public int x1, x2, y1, y2, id;

		public Rect(int _x1, int _x2, int _y1, int _y2, int _id) {
			this.x1 = _x1;
			this.x2 = _x2;
			this.y1 = _y1;
			this.y2 = _y2;
			this.id = _id;
		}
	}

	static int tree[];

	static void update(int t, int tl, int tr, int index, int value) {
		tree[t] = Math.min(tree[t], value);
		if (tl == tr) {
			tree[t] = value;
			return;
		}

		int tm = (tl + tr) / 2;
		if (index <= tm)
			update(2 * t, tl, tm, index, value);
		else
			update(2 * t + 1, tm + 1, tr, index, value);
	}

	static int inf = 1000000;

	static int getMin(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return inf;

		if (l == tl && r == tr)
			return tree[t];

		int tm = (tl + tr) / 2;
		return Math.min(getMin(2 * t, tl, tm, l, Math.min(tm, r)),
				getMin(2 * t + 1, tm + 1, tr, Math.max(l, tm + 1), r));
	}

	static void banana() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int q = nextInt();

		P a[] = new P[k];
		for (int i = 0; i < k; ++i) {
			a[i] = new P(nextInt(), nextInt());
		}

		boolean ans[] = new boolean[q];
		Rect b[] = new Rect[q];
		for (int i = 0; i < q; ++i) {
			int x1 = nextInt();
			int y1 = nextInt();
			int x2 = nextInt();
			int y2 = nextInt();

			b[i] = new Rect(x1, x2, y1, y2, i);
		}

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.y - b.y;
			}
		});

		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.y2 - b.y2;
			}

		});

		tree = new int[4 * n + 20];
		Arrays.fill(tree, inf);

		int counter = 0;
		int c = 0;
		for (int i = 1; i <= m; ++i) {
			while (counter < k && a[counter].y == i) {
				update(1, 1, n, a[counter].x, i);
				++counter;
			}

			while (c < q && b[c].y2 == i) {
				int val = getMin(1, 1, n, b[c].x1, b[c].x2);
				if (val != inf && val >= b[c].y1)
					ans[b[c].id] = true;

				++c;
			}
		}

		counter = 0;
		c = 0;
		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.x2 - b.x2;
			}
		});

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.x - b.x;
			}
		});

		tree = new int[4 * m + 20];
		Arrays.fill(tree, inf);
		counter = 0;
		c = 0;
		for (int i = 1; i <= n; ++i) {
			while (counter < k && a[counter].x == i) {
				update(1, 1, m, a[counter].y, i);
				++counter;
			}

			while (c < q && b[c].x2 == i) {
				int val = getMin(1, 1, m, b[c].y1, b[c].y2);
				if (val != inf && val >= b[c].x1)
					ans[b[c].id] = true;

				++c;
			}
		}

		for (int i = 0; i < q; ++i) {
			writer.println(ans[i] ? "YES" : "NO");
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main {
	static BufferedReader reader;
	static StringTokenizer tokenizer;
	static PrintWriter writer;

	static int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	static long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	static double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	static boolean eof = false;

	static String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	public static void main(String[] args) throws IOException {
		tokenizer = null;
		// reader = new BufferedReader(new FileReader("grave.in"));
		// writer = new PrintWriter(new FileWriter("grave.out"));
		reader = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		writer = new PrintWriter(System.out);
		banana();
		reader.close();
		writer.close();
	}

	static class P {
		public int x, y;

		public P(int _x, int _y) {
			this.x = _x;
			this.y = _y;
		}
	}

	static class Rect {
		public int x1, x2, y1, y2, id;

		public Rect(int _x1, int _x2, int _y1, int _y2, int _id) {
			this.x1 = _x1;
			this.x2 = _x2;
			this.y1 = _y1;
			this.y2 = _y2;
			this.id = _id;
		}
	}

	static int tree[];

	static void update(int t, int tl, int tr, int index, int value) {
		tree[t] = Math.min(tree[t], value);
		if (tl == tr) {
			tree[t] = value;
			return;
		}

		int tm = (tl + tr) / 2;
		if (index <= tm)
			update(2 * t, tl, tm, index, value);
		else
			update(2 * t + 1, tm + 1, tr, index, value);
	}

	static int inf = 1000000;

	static int getMin(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return inf;

		if (l == tl && r == tr)
			return tree[t];

		int tm = (tl + tr) / 2;
		return Math.min(getMin(2 * t, tl, tm, l, Math.min(tm, r)),
				getMin(2 * t + 1, tm + 1, tr, Math.max(l, tm + 1), r));
	}

	static void banana() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int q = nextInt();

		P a[] = new P[k];
		for (int i = 0; i < k; ++i) {
			a[i] = new P(nextInt(), nextInt());
		}

		boolean ans[] = new boolean[q];
		Rect b[] = new Rect[q];
		for (int i = 0; i < q; ++i) {
			int x1 = nextInt();
			int y1 = nextInt();
			int x2 = nextInt();
			int y2 = nextInt();

			b[i] = new Rect(x1, x2, y1, y2, i);
		}

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.y - b.y;
			}
		});

		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.y2 - b.y2;
			}

		});

		tree = new int[4 * n + 20];
		Arrays.fill(tree, 0);

		int counter = 0;
		int c = 0;
		for (int i = 1; i <= m; ++i) {
			while (counter < k && a[counter].y == i) {
				update(1, 1, n, a[counter].x, i);
				++counter;
			}

			while (c < q && b[c].y2 == i) {
				int val = getMin(1, 1, n, b[c].x1, b[c].x2);
				if (val != inf && val >= b[c].y1)
					ans[b[c].id] = true;

				++c;
			}
		}

		counter = 0;
		c = 0;
		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.x2 - b.x2;
			}
		});

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.x - b.x;
			}
		});

		tree = new int[4 * m + 20];
		counter = 0;
		c = 0;
		for (int i = 1; i <= n; ++i) {
			while (counter < k && a[counter].x == i) {
				update(1, 1, m, a[counter].y, i);
				++counter;
			}

			while (c < q && b[c].x2 == i) {
				int val = getMin(1, 1, m, b[c].y1, b[c].y2);
				if (val != inf && val >= b[c].x1)
					ans[b[c].id] = true;

				++c;
			}
		}

		for (int i = 0; i < q; ++i) {
			writer.println(ans[i] ? "YES" : "NO");
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main {
	static BufferedReader reader;
	static StringTokenizer tokenizer;
	static PrintWriter writer;

	static int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	static long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	static double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	static boolean eof = false;

	static String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	public static void main(String[] args) throws IOException {
		tokenizer = null;
		// reader = new BufferedReader(new FileReader("grave.in"));
		// writer = new PrintWriter(new FileWriter("grave.out"));
		reader = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		writer = new PrintWriter(System.out);
		banana();
		reader.close();
		writer.close();
	}

	static class P {
		public int x, y;

		public P(int _x, int _y) {
			this.x = _x;
			this.y = _y;
		}
	}

	static class Rect {
		public int x1, x2, y1, y2, id;

		public Rect(int _x1, int _x2, int _y1, int _y2, int _id) {
			this.x1 = _x1;
			this.x2 = _x2;
			this.y1 = _y1;
			this.y2 = _y2;
			this.id = _id;
		}
	}

	static int tree[];

	static void update(int t, int tl, int tr, int index, int value) {
		tree[t] = Math.min(tree[t], value);
		if (tl == tr) {
			tree[t] = value;
			return;
		}

		int tm = (tl + tr) / 2;
		if (index <= tm)
			update(2 * t, tl, tm, index, value);
		else
			update(2 * t + 1, tm + 1, tr, index, value);
	}

	static int inf = 1000000;

	static int getMin(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return inf;

		if (l == tl && r == tr)
			return tree[t];

		int tm = (tl + tr) / 2;
		return Math.min(getMin(2 * t, tl, tm, l, Math.min(tm, r)),
				getMin(2 * t + 1, tm + 1, tr, Math.max(l, tm + 1), r));
	}

	static void banana() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int q = nextInt();

		P a[] = new P[k];
		for (int i = 0; i < k; ++i) {
			a[i] = new P(nextInt(), nextInt());
		}

		boolean ans[] = new boolean[q];
		Rect b[] = new Rect[q];
		for (int i = 0; i < q; ++i) {
			int x1 = nextInt();
			int y1 = nextInt();
			int x2 = nextInt();
			int y2 = nextInt();

			b[i] = new Rect(x1, x2, y1, y2, i);
		}

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.y - b.y;
			}
		});

		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.y2 - b.y2;
			}

		});

		tree = new int[4 * n + 20];
		Arrays.fill(tree, 0);

		int counter = 0;
		int c = 0;
		for (int i = 1; i <= m; ++i) {
			while (counter < k && a[counter].y == i) {
				update(1, 1, n, a[counter].x, i);
				++counter;
			}

			while (c < q && b[c].y2 == i) {
				int val = getMin(1, 1, n, b[c].x1, b[c].x2);
				if (val != inf && val >= b[c].y1)
					ans[b[c].id] = true;

				++c;
			}
		}

		counter = 0;
		c = 0;
		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.x2 - b.x2;
			}
		});

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.x - b.x;
			}
		});

		tree = new int[4 * m + 20];
		Arrays.fill(tree, 0);
		counter = 0;
		c = 0;
		for (int i = 1; i <= n; ++i) {
			while (counter < k && a[counter].x == i) {
				update(1, 1, m, a[counter].y, i);
				++counter;
			}

			while (c < q && b[c].x2 == i) {
				int val = getMin(1, 1, m, b[c].y1, b[c].y2);
				if (val != inf && val >= b[c].x1)
					ans[b[c].id] = true;

				++c;
			}
		}

		for (int i = 0; i < q; ++i) {
			writer.println(ans[i] ? "YES" : "NO");
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main {
	static BufferedReader reader;
	static StringTokenizer tokenizer;
	static PrintWriter writer;

	static int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	static long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	static double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	static boolean eof = false;

	static String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	public static void main(String[] args) throws IOException {
		tokenizer = null;
		// reader = new BufferedReader(new FileReader("grave.in"));
		// writer = new PrintWriter(new FileWriter("grave.out"));
		reader = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		writer = new PrintWriter(System.out);
		banana();
		reader.close();
		writer.close();
	}

	static class P {
		public int x, y;

		public P(int _x, int _y) {
			this.x = _x;
			this.y = _y;
		}
	}

	static class Rect {
		public int x1, x2, y1, y2, id;

		public Rect(int _x1, int _x2, int _y1, int _y2, int _id) {
			this.x1 = _x1;
			this.x2 = _x2;
			this.y1 = _y1;
			this.y2 = _y2;
			this.id = _id;
		}
	}

	static int tree[];
	static int maxTree[];

	static void update(int t, int tl, int tr, int index, int value) {
		tree[t] = Math.min(tree[t], value);

		if (tl == tr) {
			tree[t] = value;
			return;
		}

		int tm = (tl + tr) / 2;
		if (index <= tm)
			update(2 * t, tl, tm, index, value);
		else
			update(2 * t + 1, tm + 1, tr, index, value);
		tree[t] = Math.min(tree[2 * t], tree[2 * t + 1]);
	}

	static int inf = 1000000;

	static int getMax(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return 0;
		if (l == tl && r == tr)
			return maxTree[t];
		int tm = (tl + tr) / 2;
		return Math.max(getMax(2 * t, tl, tm, l, Math.min(r, tm)),
				getMax(2 * t + 1, tm + 1, tr, Math.max(tm + 1, l), r));
	}

	static int getMin(int t, int tl, int tr, int l, int r) {
		if (l > r)
			return inf;

		if (l == tl && r == tr)
			return tree[t];

		int tm = (tl + tr) / 2;
		return Math.min(getMin(2 * t, tl, tm, l, Math.min(tm, r)),
				getMin(2 * t + 1, tm + 1, tr, Math.max(l, tm + 1), r));
	}

	static void banana() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int q = nextInt();

		P a[] = new P[k];
		for (int i = 0; i < k; ++i) {
			a[i] = new P(nextInt(), nextInt());
		}

		boolean ans[] = new boolean[q];
		Rect b[] = new Rect[q];
		for (int i = 0; i < q; ++i) {
			int x1 = nextInt();
			int y1 = nextInt();
			int x2 = nextInt();
			int y2 = nextInt();

			b[i] = new Rect(x1, x2, y1, y2, i);
		}

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.y - b.y;
			}
		});

		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.y2 - b.y2;
			}

		});

		tree = new int[4 * n + 20];
		Arrays.fill(tree, 0);

		int counter = 0;
		int c = 0;
		for (int i = 1; i <= m; ++i) {
			while (counter < k && a[counter].y == i) {
				update(1, 1, n, a[counter].x, i);
				++counter;
			}

			while (c < q && b[c].y2 == i) {
				int val = getMin(1, 1, n, b[c].x1, b[c].x2);
				if (val != inf && val >= b[c].y1)
					ans[b[c].id] = true;

				++c;
			}
		}

		counter = 0;
		c = 0;
		Arrays.sort(b, new Comparator<Rect>() {

			@Override
			public int compare(Rect a, Rect b) {
				return a.x2 - b.x2;
			}
		});

		Arrays.sort(a, new Comparator<P>() {

			@Override
			public int compare(P a, P b) {
				return a.x - b.x;
			}
		});

		tree = new int[4 * m + 20];
		Arrays.fill(tree, 0);
		counter = 0;
		c = 0;
		for (int i = 1; i <= n; ++i) {
			while (counter < k && a[counter].x == i) {
				update(1, 1, m, a[counter].y, i);
				++counter;
			}

			while (c < q && b[c].x2 == i) {
				int val = getMin(1, 1, m, b[c].y1, b[c].y2);
				if (val >= b[c].x1 && val != inf)
					ans[b[c].id] = true;

				++c;
			}
		}

		for (int i = 0; i < q; ++i) {
			writer.println(ans[i] ? "YES" : "NO");
		}
	}
}


import java.io.*;
import java.util.*;

public class A {
	FastScanner in;
	PrintWriter out;

	int n, m, k, q;

	class Point {
		int x, y;

		public Point(int x, int y) {
			super();
			this.x = x;
			this.y = y;
		}
	}

	class Query {
		Point p0, p1;
		int num;

		public Query(Point p0, Point p1) {
			super();
			this.p0 = p0;
			this.p1 = p1;
		}
	}

	class SegmentTree {
		int[] t, a;
		int n;

		public SegmentTree(int[] a) {
			n = a.length;
			t = new int[4 * n];
			this.a = a;
			build(0, 0, n);
		}

		void build(int v, int l, int r) {
			if (r - l == 1) {
				t[v] = a[l];
				return;
			}
			int m = (l + r) / 2;
			build(2 * v + 1, l, m);
			build(2 * v + 2, m, r);
			t[v] = Math.min(t[2 * v + 1], t[2 * v + 2]);
		}

		void setTo(int i, int val) {
			setTo(0, 0, n, i, val);
		}

		void setTo(int v, int tl, int tr, int i, int val) {
			if (i >= tr || i < tl) {
				return;
			}
			if (tr - tl == 1) {
				a[i] = val;
				t[v] = a[i];
				return;
			}
			int tm = (tl + tr) / 2;
			if (i < tm)
				setTo(2 * v + 1, tl, tm, i, val);
			else
				setTo(2 * v + 2, tm, tr, i, val);
		}

		int getMin(int l, int r) {
			return getMin(0, 0, n, l, r);
		}

		int getMin(int v, int tl, int tr, int l, int r) {
			if (tl >= r || tr <= l)
				return Integer.MAX_VALUE;
			if (tl >= l && tr <= r) {
				return t[v];
			}
			int tm = (tl + tr) / 2;
			int val0 = getMin(2 * v + 1, tl, tm, l, r);
			int val1 = getMin(2 * v + 2, tm, tr, l, r);
			return Math.min(val0, val1);
		}
	}

	void go(Query[] qs, Point[] pts, boolean[] can) {
		Arrays.sort(qs, new Comparator<Query>() {

			@Override
			public int compare(Query o1, Query o2) {
				if (o1.p1.y != o2.p1.y)
					return Integer.compare(o1.p1.y, o2.p1.y);
				return Integer.compare(o1.num, o2.num);
			}
		});
		Arrays.sort(pts, new Comparator<Point>() {

			@Override
			public int compare(Point o1, Point o2) {
				if (o1.y != o2.y)
					return Integer.compare(o1.y, o2.y);
				return Integer.compare(o1.x, o2.x);
			}
		});
		int[] a = new int[n];
		Arrays.fill(a, Integer.MIN_VALUE);
		SegmentTree segTree = new SegmentTree(a);
		int p = 0;
		for (int i = 0; i < qs.length; i++) {
			int maxY = qs[i].p1.y;
			while (p < pts.length && pts[p].y <= maxY) {
				segTree.setTo(pts[p].x, pts[p].y);
				p++;
			}
			int min = segTree.getMin(qs[i].p0.x, qs[i].p1.x + 1);
			if (min >= qs[i].p0.y)
				can[qs[i].num] = true;
		}
	}

	Point swap(Point p) {
		return new Point(p.y, p.x);
	}

	void solve() {
		n = in.nextInt(); m = in.nextInt();
		int k = in.nextInt(), q = in.nextInt();
		Point[] pts = new Point[k];
		for (int i = 0; i < k; i++) {
			pts[i] = new Point(in.nextInt() - 1, in.nextInt() - 1);
		}
		Query[] qs = new Query[q];
		boolean[] can = new boolean[q];
		for (int i = 0; i < q; i++) {
			qs[i] = new Query(new Point(in.nextInt() - 1, in.nextInt() - 1), new Point(in.nextInt() - 1, in.nextInt() - 1));
			qs[i].num = i;
		}
		go(qs, pts, can);
		for (int i = 0; i < k; i++) {
			pts[i] = swap(pts[i]);
		}
		for (int i = 0; i < q; i++) {
			int minX = qs[i].p0.x, minY = qs[i].p0.y;
			int maxX = qs[i].p1.x, maxY = qs[i].p1.y;
			qs[i].p0 = new Point(minY, minX);
			qs[i].p1 = new Point(maxY, maxX);
		}
		int tmp = n;
		n = m;
		m = tmp;
		go(qs, pts, can);
		for (boolean b : can) {
			if (b)
				out.println("YES");
			else
				out.println("NO");
		}
	}

	void run() {
		in = new FastScanner();
		out = new PrintWriter(System.out);

		solve();

		out.close();
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(in.br.readLine());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}
	}

	public static void main(String[] args) {
		new A().run();
	}
}


import java.io.*;
import java.util.*;

public class A {
	FastScanner in;
	PrintWriter out;

	int n, m, k, q;

	class Point {
		int x, y;

		public Point(int x, int y) {
			super();
			this.x = x;
			this.y = y;
		}
	}

	class Query {
		Point p0, p1;
		int num;

		public Query(Point p0, Point p1) {
			super();
			this.p0 = p0;
			this.p1 = p1;
		}
	}

	class SegmentTree {
		int[] t, a;
		int n;

		public SegmentTree(int[] a) {
			n = a.length;
			t = new int[4 * n];
			this.a = a;
			build(0, 0, n);
		}

		void build(int v, int l, int r) {
			if (r - l == 1) {
				t[v] = a[l];
				return;
			}
			int m = (l + r) / 2;
			build(2 * v + 1, l, m);
			build(2 * v + 2, m, r);
			t[v] = Math.min(t[2 * v + 1], t[2 * v + 2]);
		}

		void setTo(int i, int val) {
			setTo(0, 0, n, i, val);
		}

		void setTo(int v, int tl, int tr, int i, int val) {
			if (i >= tr || i < tl) {
				return;
			}
			if (tr - tl == 1) {
				a[i] = val;
				t[v] = a[i];
				return;
			}
			int tm = (tl + tr) / 2;
			if (i < tm)
				setTo(2 * v + 1, tl, tm, i, val);
			else
				setTo(2 * v + 2, tm, tr, i, val);
			t[v] = Math.min(t[2 * v + 1], t[2 * v + 2]);
		}

		int getMin(int l, int r) {
			return getMin(0, 0, n, l, r);
		}

		int getMin(int v, int tl, int tr, int l, int r) {
			if (tl >= r || tr <= l)
				return Integer.MAX_VALUE;
			if (tl >= l && tr <= r) {
				return t[v];
			}
			int tm = (tl + tr) / 2;
			int val0 = getMin(2 * v + 1, tl, tm, l, r);
			int val1 = getMin(2 * v + 2, tm, tr, l, r);
			return Math.min(val0, val1);
		}
	}

	void go(Query[] qs, Point[] pts, boolean[] can) {
		Arrays.sort(qs, new Comparator<Query>() {

			@Override
			public int compare(Query o1, Query o2) {
				if (o1.p1.y != o2.p1.y)
					return Integer.compare(o1.p1.y, o2.p1.y);
				return Integer.compare(o1.num, o2.num);
			}
		});
		Arrays.sort(pts, new Comparator<Point>() {

			@Override
			public int compare(Point o1, Point o2) {
				if (o1.y != o2.y)
					return Integer.compare(o1.y, o2.y);
				return Integer.compare(o1.x, o2.x);
			}
		});
		int[] a = new int[n];
		Arrays.fill(a, Integer.MIN_VALUE);
		SegmentTree segTree = new SegmentTree(a);
		int p = 0;
		for (int i = 0; i < qs.length; i++) {
			int maxY = qs[i].p1.y;
			while (p < pts.length && pts[p].y <= maxY) {
				segTree.setTo(pts[p].x, pts[p].y);
				p++;
			}
			int min = segTree.getMin(qs[i].p0.x, qs[i].p1.x + 1);
			if (min >= qs[i].p0.y)
				can[qs[i].num] = true;
		}
	}

	Point swap(Point p) {
		return new Point(p.y, p.x);
	}

	void solve() {
		n = in.nextInt(); m = in.nextInt();
		int k = in.nextInt(), q = in.nextInt();
		Point[] pts = new Point[k];
		for (int i = 0; i < k; i++) {
			pts[i] = new Point(in.nextInt() - 1, in.nextInt() - 1);
		}
		Query[] qs = new Query[q];
		boolean[] can = new boolean[q];
		for (int i = 0; i < q; i++) {
			qs[i] = new Query(new Point(in.nextInt() - 1, in.nextInt() - 1), new Point(in.nextInt() - 1, in.nextInt() - 1));
			qs[i].num = i;
		}
		go(qs, pts, can);
		for (int i = 0; i < k; i++) {
			pts[i] = swap(pts[i]);
		}
		for (int i = 0; i < q; i++) {
			int minX = qs[i].p0.x, minY = qs[i].p0.y;
			int maxX = qs[i].p1.x, maxY = qs[i].p1.y;
			qs[i].p0 = new Point(minY, minX);
			qs[i].p1 = new Point(maxY, maxX);
		}
		int tmp = n;
		n = m;
		m = tmp;
		go(qs, pts, can);
		for (boolean b : can) {
			if (b)
				out.println("YES");
			else
				out.println("NO");
		}
	}

	void run() {
		in = new FastScanner();
		out = new PrintWriter(System.out);

		solve();

		out.close();
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(in.br.readLine());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}
	}

	public static void main(String[] args) {
		new A().run();
	}
}


import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class B {

    boolean[] vert(int n, int m, int k, int q, Point[] p) {
        boolean[] ans = new boolean[q];
        Arrays.sort(p);
        ST tree = new ST(100100);
        for (Point x : p) {
            if (x.isPoint()) {
                tree.set(x.y1, x.x1);
            } else {
                int min = tree.get(x.y1, x.y2 + 1);
                if (min < x.x1) continue;
                ans[x.id] = true;
            }
        }
        return ans;
    }

    void solve() throws IOException {
        int n = in.nextInt();
        int m = in.nextInt();
        int k = in.nextInt();
        int q = in.nextInt();
        int[] x = new int[k];
        int[] y = new int[k];
        for (int i = 0; i < k; ++i) {
            x[i] = in.nextInt();
            y[i] = in.nextInt();
        }
        int[] x1 = new int[q];
        int[] y1 = new int[q];
        int[] x2 = new int[q];
        int[] y2 = new int[q];
        for (int i = 0; i < q; ++i) {
            x1[i] = in.nextInt();
            y1[i] = in.nextInt();
            x2[i] = in.nextInt();
            y2[i] = in.nextInt();
        }
        Point[] p1 = new Point[q + k];
        int s1 = 0;
        for (int i = 0; i < k; ++i) {
            p1[s1++] = new Point(x[i], y[i]);
        }
        for (int i = 0; i < q; ++i) {
            p1[s1++] = new Point(x1[i], y1[i], x2[i], y2[i], i);
        }
        boolean[] a1 = vert(n, m, k, q, p1);

        Point[] p2 = new Point[q + k];
        int s2 = 0;
        for (int i = 0; i < k; ++i) {
            p2[s2++] = new Point(y[i], x[i]);
        }
        for (int i = 0; i < q; ++i) {
            p2[s2++] = new Point(y1[i], x1[i], y2[i], x2[i], i);
        }
        boolean[] a2 = vert(m, n, k, q, p2);
        for (int i = 0; i < q; ++i) {
            out.println(a1[i] || a2[i] ? "YES" : "NO");
        }
    }

    static FastReader in;
    static PrintWriter out;
    static PrintStream err;

    public static void main(String[] args) {
        try {
            in = new FastReader();
            out = new PrintWriter(System.out);
            err = System.err;
            new B().solve();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}

class FastReader {
    BufferedReader br;
    StringTokenizer st;

    FastReader(InputStream is) {
        br = new BufferedReader(new InputStreamReader(is));
    }

    FastReader() {
        this(System.in);
    }

    FastReader(String file) throws FileNotFoundException {
        this(new FileInputStream(file));
    }

    String nextToken() throws IOException {
        while (st == null || !st.hasMoreElements()) {
            st = new StringTokenizer(br.readLine());
        }
        return st.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
}

class ST {
    int n;
    int[] min;

    ST(int n) {
        this.n = n;
        min = new int[4 * n];
        Arrays.fill(min, Integer.MIN_VALUE);
    }

    int get(int l, int r) {
        return _get(l, r, 0, 0, n);
    }

    int _get(int l, int r, int v, int L, int R) {
        if (l <= L && R <= r) return min[v];
        if (l >= R || L >= r) return Integer.MAX_VALUE;
        int M = (L + R) / 2;
        return Math.min(_get(l, r, 2 * v + 1, L, M),
                        _get(l, r, 2 * v + 2, M, R));
    }

    void set(int pos, int val) {
        _set(pos, val, 0, 0, n);
    }

    void _set(int pos, int val, int v, int l, int r) {
        if (r - l == 1) {
            min[v] = val;
        } else {
            int m = (l + r) / 2;
            if (pos < m) {
                _set(pos, val, 2 * v + 1, l, m);
            } else {
                _set(pos, val, 2 * v + 2, m, r);
            }
            min[v] = Math.min(min[2 * v + 1], min[2 * v + 2]);
        }
    }
}

class Point implements Comparable<Point> {
    int x1, x2, y1, y2;
    int type;

    int id;

    boolean isPoint() {
        return type == -1;
    }

    Point(int x, int y) {
        x1 = x;
        x2 = x;
        y1 = y;
        y2 = y;
        type = -1;
    }

    public Point(int x1, int y1, int x2, int y2, int id) {
        this.x1 = x1;
        this.x2 = x2;
        this.y1 = y1;
        this.y2 = y2;
        this.id = id;
        type = 1;
    }

    int getPos() {
        return x2;
    }

    @Override
    public int compareTo(Point o) {
        if (getPos() != o.getPos()) return Integer.compare(getPos(), o.getPos());
        return Integer.compare(type, o.type);
    }
}


import java.util.Arrays;
import java.util.ArrayList;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.io.BufferedReader;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Vadim Semenov
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int rows = in.nextInt();
        int columns = in.nextInt();
        int rooks = in.nextInt();
        int queries = in.nextInt();
        List<Integer>[][] rooksHere = new List[2][];
        rooksHere[0] = new List[rows];
        rooksHere[1] = new List[columns];
        List<Integer>[][] endsHere = new List[2][];
        endsHere[0] = new List[rows];
        endsHere[1] = new List[columns];
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < endsHere[i].length; ++j) {
                rooksHere[i][j] = new ArrayList<>();
                endsHere[i][j] = new ArrayList<>();
            }
        }
        for (int i = 0; i < rooks; ++i) {
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            rooksHere[0][x].add(y);
            rooksHere[1][y].add(x);
        }
        int[][][] area = new int[2][2][queries];
        for (int i = 0; i < queries; ++i) {
            for (int j = 0; j < 2; ++j) {
                for (int k = 0; k < 2; ++k) {
                    area[j][k][i] = in.nextInt() - 1;
                    if (j == 1) {
                        endsHere[k][area[j][k][i]].add(i);
                    }
                }
            }
        }
        boolean[] isProtected = new boolean[queries];
        for (int dir = 0; dir < 2; ++dir) {
            RMQ rmq = new RMQ(endsHere[dir ^ 1].length);
            for (int coordinate = 0; coordinate < endsHere[dir].length; ++coordinate) {
                for (int i : rooksHere[dir][coordinate]) {
                    rmq.update(i, coordinate);
                }
                for (int i : endsHere[dir][coordinate]) {
                    isProtected[i] |= rmq.query(area[0][dir ^ 1][i], area[1][dir ^ 1][i]) >= area[0][dir][i];
                }
            }
        }
        for (boolean yes : isProtected) {
            out.println(yes ? "YES" : "NO");
        }
    }

    private static class RMQ {
        private int[] data;
        private int offset;

        public RMQ(int capacity) {
            offset = Integer.highestOneBit(capacity);
            if ((capacity & capacity - 1) != 0) offset <<= 1;
            data = new int[offset << 1];
            Arrays.fill(data, -1);
        }

        public void update(int at, int val) {
            at += offset;
            data[at] = val;
            at >>>= 1;
            while (at > 0) {
                data[at] = Math.min(data[at << 1], data[(at << 1) | 1]);
                at >>>= 1;
            }
        }

        public int query(int from, int to) {
            from += offset;
            to += offset;
            int result = Integer.MAX_VALUE;
            while (from <= to) {
                if ((from & 1) == 1) {
                    result = Math.min(result, data[from]);
                    from++;
                }
                if ((to & 1) == 0) {
                    result = Math.min(result, data[to]);
                    to--;
                }
                from >>>= 1;
                to >>>= 1;
            }
            return result;
        }
    }
}

class InputReader {
    private final BufferedReader reader;
    private StringTokenizer tokenizer;

    public InputReader(InputStream in) {
        reader = new BufferedReader(new InputStreamReader(in));
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(readLine());
        }
        return tokenizer.nextToken();
    }

    public String readLine() {
        String line;
        try {
            line = reader.readLine();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return line;
    }
}


import java.util.Arrays;
import java.util.ArrayList;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.io.BufferedReader;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Vadim Semenov
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int rows = in.nextInt();
        int columns = in.nextInt();
        int rooks = in.nextInt();
        int queries = in.nextInt();
        List<Integer>[][] rooksHere = new List[2][];
        rooksHere[0] = new List[rows];
        rooksHere[1] = new List[columns];
        List<Integer>[][] endsHere = new List[2][];
        endsHere[0] = new List[rows];
        endsHere[1] = new List[columns];
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < endsHere[i].length; ++j) {
                rooksHere[i][j] = new ArrayList<>();
                endsHere[i][j] = new ArrayList<>();
            }
        }
        for (int i = 0; i < rooks; ++i) {
            int x = in.nextInt() - 1;
            int y = in.nextInt() - 1;
            rooksHere[0][x].add(y);
            rooksHere[1][y].add(x);
        }
        int[][][] area = new int[2][2][queries];
        for (int i = 0; i < queries; ++i) {
            for (int j = 0; j < 2; ++j) {
                for (int k = 0; k < 2; ++k) {
                    area[j][k][i] = in.nextInt() - 1;
                    if (j == 1) {
                        endsHere[k][area[j][k][i]].add(i);
                    }
                }
            }
        }
        boolean[] isProtected = new boolean[queries];
        for (int dir = 0; dir < 2; ++dir) {
            RMQ rmq = new RMQ(endsHere[dir ^ 1].length);
            for (int coordinate = 0; coordinate < endsHere[dir].length; ++coordinate) {
                for (int i : rooksHere[dir][coordinate]) {
                    rmq.update(i, coordinate);
                }
                for (int i : endsHere[dir][coordinate]) {
                    isProtected[i] |= rmq.query(area[0][dir ^ 1][i], area[1][dir ^ 1][i]) >= area[0][dir][i];
                }
            }
        }
        for (boolean yes : isProtected) {
            out.println(yes ? "YES" : "NO");
        }
    }

    private static class RMQ {
        private int[] data;
        private int offset;

        public RMQ(int capacity) {
            offset = Integer.highestOneBit(capacity);
            if ((capacity & capacity - 1) != 0) offset <<= 1;
            data = new int[offset << 1];
            Arrays.fill(data, Integer.MAX_VALUE);
        }

        public void update(int at, int val) {
            at += offset;
            data[at] = val;
            at >>>= 1;
            while (at > 0) {
                data[at] = Math.min(data[at << 1], data[(at << 1) | 1]);
                at >>>= 1;
            }
        }

        public int query(int from, int to) {
            from += offset;
            to += offset;
            int result = Integer.MAX_VALUE;
            while (from <= to) {
                if ((from & 1) == 1) {
                    result = Math.min(result, data[from]);
                    if (data[from] == Integer.MAX_VALUE) {
                        result = -1;
                    }
                    from++;
                }
                if ((to & 1) == 0) {
                    result = Math.min(result, data[to]);
                    if (data[to] == Integer.MAX_VALUE) {
                        result = -1;
                    }
                    to--;
                }
                from >>>= 1;
                to >>>= 1;
            }
            return result;
        }
    }
}

class InputReader {
    private final BufferedReader reader;
    private StringTokenizer tokenizer;

    public InputReader(InputStream in) {
        reader = new BufferedReader(new InputStreamReader(in));
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(readLine());
        }
        return tokenizer.nextToken();
    }

    public String readLine() {
        String line;
        try {
            line = reader.readLine();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return line;
    }
}


import java.io.*;
import java.util.*;

public class E {

	FastScanner in;
	PrintWriter out;

	void solve() {
		int n = in.nextInt(), m = in.nextInt(), k = in.nextInt(), q = in
				.nextInt();
		int[] x = new int[k], y = new int[k];
		for (int i = 0; i < k; i++) {
			x[i] = in.nextInt() - 1;
			y[i] = in.nextInt() - 1;
		}
		int[] x1 = new int[q], x2 = new int[q], y1 = new int[q], y2 = new int[q];
		for (int i = 0; i < q; i++) {
			x1[i] = in.nextInt() - 1;
			y1[i] = in.nextInt() - 1;
			x2[i] = in.nextInt() - 1;
			y2[i] = in.nextInt() - 1;
		}
		boolean[] ans = new boolean[q];
		for (int rot = 0; rot < 2; rot++) {
			List<Event> events = new ArrayList<>();

			for (int i = 0; i < k; i++) {
				events.add(new Event(x[i], 0, i));
			}
			for (int i = 0; i < q; i++) {
				events.add(new Event(x2[i], 1, i));
			}
			Collections.sort(events);

			SegmentTree st = new SegmentTree(m);
			for (Event e : events) {
				if (e.type == 0) {
					st.set(y[e.id], x[e.id]);
				} else {
					int from = y1[e.id], to = y2[e.id];
					int min = st.get(from, to);
					if (min >= x1[e.id]) {
						ans[e.id] = true;
					}
				}
			}

			for (int i = 0; i < k; i++) {
				int tmp = x[i];
				x[i] = y[i];
				y[i] = tmp;
			}
			for (int i = 0; i < q; i++) {
				int tmp = x1[i];
				x1[i] = y1[i];
				y1[i] = tmp;

				tmp = x2[i];
				x2[i] = y2[i];
				y2[i] = tmp;
			}

			int tmp = n;
			n = m;
			m = tmp;
		}

		for (int i = 0; i < q; i++) {
			out.println(ans[i] ? "YES" : "NO");
		}
	}

	class Event implements Comparable<Event> {
		int pos, type;
		int id;

		public Event(int pos, int type, int id) {
			super();
			this.pos = pos;
			this.type = type;
			this.id = id;
		}

		@Override
		public int compareTo(Event o) {
			int t = Integer.compare(pos, o.pos);
			if (t == 0) {
				return Integer.compare(type, o.type);
			}
			return t;
		}
	}

	class SegmentTree {
		int[] min;
		int size;

		public SegmentTree(int n) {
			min = new int[4 * n];
			Arrays.fill(min, -1);
			size = n;
		}

		void set(int pos, int val) {
			set(0, size, pos, val, 0);
		}

		void set(int left, int right, int pos, int val, int i) {
			if (left + 1 == right) {
				min[i] = val;
				return;
			}
			int mid = (left + right) >> 1;
			if (pos < mid) {
				set(left, mid, pos, val, 2 * i + 1);
			} else {
				set(mid, right, pos, val, 2 * i + 2);
			}
			min[i] = Math.min(min[2 * i + 1], min[2 * i + 2]);
		}

		int get(int l, int r) {
			return get(0, size, l, r + 1, 0);
		}

		int get(int left, int right, int l, int r, int i) {
			if (l <= left && right <= r) {
				return min[i];
			}
			if (right <= l || r <= left) {
				return Integer.MAX_VALUE;
			}
			int mid = (left + right) >> 1;
			int ans1 = get(left, mid, l, r, 2 * i + 1);
			int ans2 = get(mid, right, l, r, 2 * i + 2);
			return Math.min(ans1, ans2);
		}
	}

	class BIT {
		int[] tree;

		public BIT(int n) {
			tree = new int[n];
		}

		int get(int from, int to) {
			int res = get(to);
			if (from > 0) {
				res -= get(from - 1);
			}
			return res;
		}

		int get(int pos) {
			int res = 0;
			while (pos >= 0) {
				res += tree[pos];
				pos = (pos & (pos + 1)) - 1;
			}
			return res;
		}

		void add(int pos) {
			while (pos < tree.length) {
				tree[pos]++;
				pos |= pos + 1;
			}
		}
	}

	void run() {
		in = new FastScanner();
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		public FastScanner(String s) {
			try {
				br = new BufferedReader(new FileReader(s));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}

		String nextToken() {
			while (st == null || !st.hasMoreElements()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(nextToken());
		}

		long nextLong() {
			return Long.parseLong(nextToken());
		}

		double nextDouble() {
			return Double.parseDouble(nextToken());
		}
	}

	public static void main(String[] args) {
		new E().run();
	}
}


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.SortedSet;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * #
 *
 * @author pttrung
 */
public class E_VK2015_Round1 {

	public static long MOD = 1000000007;

	public static void main(String[] args) throws FileNotFoundException {
		// PrintWriter out = new PrintWriter(new FileOutputStream(new File(
		// "output.txt")));
		PrintWriter out = new PrintWriter(System.out);
		Scanner in = new Scanner();
		int n = in.nextInt();
		int m = in.nextInt();
		int k = in.nextInt();
		int h = in.nextInt();
		Point[] data = new Point[k];
		for (int i = 0; i < k; i++) {
			data[i] = new Point(in.nextInt(), in.nextInt());
		}
		Square[] q = new Square[h];
		for (int i = 0; i < h; i++) {
			q[i] = new Square(i, in.nextInt(), in.nextInt(), in.nextInt(),
					in.nextInt());
		}
		Arrays.sort(q, new Comparator<Square>() {

			@Override
			public int compare(Square o1, Square o2) {
				// TODO Auto-generated method stub
				return Integer.compare(o1.x2, o2.x2);
			}
		});
		Arrays.sort(data);
	//	System.out.println(Arrays.toString(data));
		boolean[] result = new boolean[h];
		int[] tree = new int[4 * Math.max(n, m) + 10];
		Arrays.fill(tree, -1);
		int index = 0;
		for (int i = 0; i < h; i++) {
			while (index < k && data[index].x <= q[i].x2) {
				update(0, data[index].y, data[index].x, 1, m, tree);
				index++;
			}
			int v = get(0, q[i].y1, q[i].y2, 1, m, tree);

			if (v < q[i].x1) {

			} else {
				result[q[i].index] = true;
			}

		}
		Arrays.sort(q, new Comparator<Square>() {

			@Override
			public int compare(Square o1, Square o2) {
				// TODO Auto-generated method stub
				return Integer.compare(o1.y2, o2.y2);
			}
		});
		Arrays.sort(data, new Comparator<Point>() {

			@Override
			public int compare(Point o1, Point o2) {
				// TODO Auto-generated method stub
				return Integer.compare(o1.y, o2.y);
			}
		});

		tree = new int[4 * Math.max(n, m) + 10];
		Arrays.fill(tree, -1);
		index = 0;
		for (int i = 0; i < h; i++) {
			while (index < k && data[index].y <= q[i].y2) {
				update(0, data[index].x, data[index].y, 1, n, tree);
				index++;
			}
			int v = get(0, q[i].x1, q[i].x2, 1, n, tree);
//			System.out.println(v + " " + " " + q[i].x1 + " " + q[i].x2 + " "
//					+ q[i].index);
			if (v < q[i].y1) {

			} else {
				result[q[i].index] = true;
			}
		}
		for (boolean v : result) {
			if (v) {
				out.println("YES");
			} else {
				out.println("NO");
			}
		}

		out.close();
	}

	static int left(int index) {
		return 2 * index + 1;
	}

	static int right(int index) {
		return 2 * index + 2;
	}

	static int get(int index, int l1, int r1, int l, int r, int[] tree) {
		if (l > r1 || r < l1) {
			return Integer.MAX_VALUE;
		}
		if (l1 <= l && r <= r1) {
			return tree[index];
		}
		int mid = (l + r) >> 1;
		int a = get(left(index), l1, r1, l, mid, tree);
		int b = get(right(index), l1, r1, mid + 1, r, tree);

		return Math.min(a, b);

	}

	static void update(int index, int p, int v, int l, int r, int[] tree) {
		if (l > p || r < p) {
			return;
		}
		if (l == p && r == p) {
			tree[index] = v;
			return;
		}
		int mid = (l + r) >> 1;
		update(left(index), p, v, l, mid, tree);
		update(right(index), p, v, mid + 1, r, tree);

		tree[index] = Math.min(tree[left(index)], tree[right(index)]);

	}

	static class Square {
		int index, x1, y1, x2, y2;

		public Square(int index, int x1, int y1, int x2, int y2) {
			super();
			this.index = index;
			this.x1 = x1;
			this.y1 = y1;
			this.x2 = x2;
			this.y2 = y2;
		}
	}

	public static int[] KMP(String val) {
		int i = 0;
		int j = -1;
		int[] result = new int[val.length() + 1];
		result[0] = -1;
		while (i < val.length()) {
			while (j >= 0 && val.charAt(j) != val.charAt(i)) {
				j = result[j];
			}
			j++;
			i++;
			result[i] = j;
		}
		return result;

	}

	public static boolean nextPer(int[] data) {
		int i = data.length - 1;
		while (i > 0 && data[i] < data[i - 1]) {
			i--;
		}
		if (i == 0) {
			return false;
		}
		int j = data.length - 1;
		while (data[j] < data[i - 1]) {
			j--;
		}
		int temp = data[i - 1];
		data[i - 1] = data[j];
		data[j] = temp;
		Arrays.sort(data, i, data.length);
		return true;
	}

	public static int digit(long n) {
		int result = 0;
		while (n > 0) {
			n /= 10;
			result++;
		}
		return result;
	}

	public static double dist(long a, long b, long x, long y) {
		double val = (b - a) * (b - a) + (x - y) * (x - y);
		val = Math.sqrt(val);
		double other = x * x + a * a;
		other = Math.sqrt(other);
		return val + other;

	}

	public static class Point implements Comparable<Point> {

		int x, y;

		public Point(int start, int end) {
			this.x = start;
			this.y = end;
		}

		@Override
		public int hashCode() {
			int hash = 5;
			hash = 47 * hash + this.x;
			hash = 47 * hash + this.y;
			return hash;
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == null) {
				return false;
			}
			if (getClass() != obj.getClass()) {
				return false;
			}
			final Point other = (Point) obj;
			if (this.x != other.x) {
				return false;
			}
			if (this.y != other.y) {
				return false;
			}
			return true;
		}

		@Override
		public String toString() {
			return "Point [x=" + x + ", y=" + y + "]";
		}

		@Override
		public int compareTo(Point o) {
			return x - o.x;
		}
	}

	public static class FT {

		long[] data;

		FT(int n) {
			data = new long[n];
		}

		public void update(int index, long value) {
			while (index < data.length) {
				data[index] += value;
				index += (index & (-index));
			}
		}

		public long get(int index) {
			long result = 0;
			while (index > 0) {
				result += data[index];
				index -= (index & (-index));
			}
			return result;

		}
	}

	public static long gcd(long a, long b) {
		if (b == 0) {
			return a;
		}
		return gcd(b, a % b);
	}

	public static long pow(long a, long b) {
		if (b == 0) {
			return 1;
		}
		if (b == 1) {
			return a;
		}
		long val = pow(a, b / 2);
		if (b % 2 == 0) {
			return val * val % MOD;
		} else {
			return val * (val * a % MOD) % MOD;

		}
	}

	static class Scanner {

		BufferedReader br;
		StringTokenizer st;

		public Scanner() throws FileNotFoundException {
			// System.setOut(new PrintStream(new
			// BufferedOutputStream(System.out), true));
			br = new BufferedReader(new InputStreamReader(System.in));
			// br = new BufferedReader(new InputStreamReader(new
			// FileInputStream(new File("input.txt"))));
		}

		public String next() {

			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (Exception e) {
					throw new RuntimeException();
				}
			}
			return st.nextToken();
		}

		public long nextLong() {
			return Long.parseLong(next());
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}

		public String nextLine() {
			st = null;
			try {
				return br.readLine();
			} catch (Exception e) {
				throw new RuntimeException();
			}
		}

		public boolean endLine() {
			try {
				String next = br.readLine();
				while (next != null && next.trim().isEmpty()) {
					next = br.readLine();
				}
				if (next == null) {
					return true;
				}
				st = new StringTokenizer(next);
				return st.hasMoreTokens();
			} catch (Exception e) {
				throw new RuntimeException();
			}
		}
	}
}


import java.util.Arrays;
import java.util.ArrayList;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Artem Gilmudinov
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		Reader in = new Reader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
    class Rectangle {
        public int x1, y1, x2, y2, id;
        public Rectangle(int x1, int y1, int x2, int y2, int id) {
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
            this.id = id;
        }
    }

    class Tower {
        public int x, y;
        public Tower(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    public void solve(int testNumber, Reader in, PrintWriter out) {
        int n, m, k, q;
        n = in.ni(); m = in.ni(); k = in.ni(); q = in.ni();
        Tower[] towers = new Tower[k];
        Rectangle[] rectangles = new Rectangle[q];
        for(int i = 0; i < k; i++) {
            towers[i] = new Tower(in.ni() - 1, in.ni() - 1);
        }
        for(int i = 0; i < q; i++ ){
            rectangles[i] = new Rectangle(in.ni() - 1, in.ni() - 1, in.ni() - 1, in.ni() - 1, i);
        }
        HashMap<Integer, ArrayList<Integer>> colMap = new HashMap<>();
        HashMap<Integer, ArrayList<Integer>> rowMap = new HashMap<>();
        for(int i = 0; i < k; i++) {
            ArrayList<Integer> list = colMap.get(towers[i].y);
            if(list == null) {
                list = new ArrayList<>();
            }
            list.add(towers[i].x);
            colMap.put(towers[i].y, list);
            list = rowMap.get(towers[i].x);
            if(list == null) {
                list = new ArrayList<>();
            }
            list.add(towers[i].y);
            rowMap.put(towers[i].x, list);
        }
        HashMap<Integer, ArrayList<Integer>> rectCol = new HashMap<>();
        HashMap<Integer, ArrayList<Integer>> rectRow = new HashMap<>();
        for(int i = 0; i < q; i++) {
            ArrayList<Integer> list = rectCol.get(rectangles[i].y2);
            if(list == null) {
                list = new ArrayList<>();
            }
            list.add(i);
            rectCol.put(rectangles[i].y2, list);
            list = rectRow.get(rectangles[i].x2);
            if(list == null) {
                list = new ArrayList<>();
            }
            list.add(i);
            rectRow.put(rectangles[i].x2, list);

        }
        int[] last = new int[n];
        Arrays.fill(last, -1);
        SegmentTreeInt st = new SegmentTreeInt(last, Integer.MAX_VALUE, new SegmentTreeInt.Operation() {
            public int get(int x, int y) {
                return Math.min(x, y);
            }
        });
        boolean[] col = new boolean[q];
        boolean[] row = new boolean[q];
        for(int i = 0; i < m; i++) {
            ArrayList<Integer> list = colMap.get(i);
            if(list != null) {
                for(int j = 0; j < list.size(); j++) {
                    st.update(0, st.numberOfLeafs - 1, list.get(j), 0, i);
                }
            }
            list = rectCol.get(i);
            if(list != null) {
                for(int j = 0; j < list.size(); j++) {
                    Rectangle rect = rectangles[list.get(j)];
                    int min = st.get(0, st.numberOfLeafs - 1, rect.x1, rect.x2, 0);
                    if(min >= rect.y1) {
                        col[rect.id] = true;
                    }
                }
            }
        }
        last = new int[m];
        Arrays.fill(last, -1);
        st = new SegmentTreeInt(last, Integer.MAX_VALUE, new SegmentTreeInt.Operation() {
            public int get(int x, int y) {
                return Math.min(x, y);
            }
        });
        for(int i = 0; i < n; i++) {
            ArrayList<Integer> list = rowMap.get(i);
            if(list != null) {
                for(int j = 0; j < list.size(); j++) {
                    st.update(0, st.numberOfLeafs - 1, list.get(j), 0, i);
                }
            }
            list = rectRow.get(i);
            if(list != null) {
                for(int j = 0; j < list.size(); j++) {
                    Rectangle rect = rectangles[list.get(j)];
                    int min = st.get(0, st.numberOfLeafs - 1, rect.y1, rect.y2, 0);
                    if(min >= rect.x1) {
                        row[rect.id] = true;
                    }
                }
            }
        }
        for(int i = 0; i < q; i++) {
            if(col[i] || row[i]) {
                out.println("YES");
            } else {
                out.println("NO");
            }
        }

    }
}

class Reader {
    private BufferedReader in;
    private StringTokenizer st = new StringTokenizer("");
    private String delim = " ";

    public Reader(InputStream in) {
        this.in = new BufferedReader(new InputStreamReader(in));
    }

    public String next() {
        if (!st.hasMoreTokens()) {
            st = new StringTokenizer(rl());
        }
        return st.nextToken(delim);
    }

    public String rl() {
        try {
            return in.readLine();
        } catch(IOException e) {
            throw new RuntimeException(e);
        }
    }

    public int ni() {
        return Integer.parseInt(next());
    }

}

class SegmentTreeInt{

    public int b[], defaultValue;
    Operation operation;
    public int numberOfLeafs;

    public static interface Operation {
        public int get(int x, int y);
    }

    public SegmentTreeInt(int[] a, int defaultValue, Operation operation) {
        this.operation = operation;
        this.defaultValue = defaultValue;
        int n = a.length;
        int size = 1;
        while(size < n) {
            size <<= 1;
        }
        numberOfLeafs = size;
        b = new int[size * 2 - 1];
        for(int i = size - 1; i < size - 1 + n; i++) {
            b[i] = a[i - size + 1];
        }
        for(int i = size - 1 + n; i < b.length; i++) {
            b[i] = defaultValue;
        }
        for(int i = size - 2; i >= 0; i--) {
            b[i] = operation.get(b[2 * i + 1], b[2 * i + 2]);
        }
    }

    public int get(int l, int r, int q_l, int q_r, int node) {
        if(q_l > q_r) {
            return defaultValue;
        }
        if(l == q_l && r == q_r) {
            return b[node];
        }
        int mid = l + (r - l) / 2;
        return operation.get(get(l, mid, q_l, Math.min(mid, q_r), node * 2 + 1),
                get(mid + 1, r, Math.max(mid + 1, q_l), q_r, node * 2 + 2));
    }

    public void update(int l, int r, int pos, int node, int value) {
        if(l == pos && r == pos) {
            b[node] = value;
            return;
        }
        int mid = l + (r - l) / 2;
        if(pos <= mid) {
            update(l, mid, pos, 2 * node + 1, value);
        } else {
            update(mid + 1, r, pos, 2 * node + 2, value);
        }
        b[node] = operation.get(b[2 * node + 1], b[2 * node + 2]);
    }
}


import java.io.*;
import java.util.*;

public class E {

	BufferedReader br;
	PrintWriter out;
	StringTokenizer st;
	boolean eof;

	static class Rook {
		int x, y;

		public Rook(int x, int y) {
			this.x = x;
			this.y = y;
		}

		static Comparator<Rook> byX = (Rook a, Rook b) -> {
			return Integer.compare(a.x, b.x);
		};
	}

	static class Query {
		int x1, y1, x2, y2, id;

		public Query(int x1, int y1, int x2, int y2, int id) {
			this.x1 = x1;
			this.y1 = y1;
			this.x2 = x2;
			this.y2 = y2;
			this.id = id;
		}

		static Comparator<Query> byX2 = (Query a, Query b) -> {
			return Integer.compare(a.x2, b.x2);
		};
	}

	static class Node {
		int l, r;
		Node left, right;
		int min;

		public Node(int l, int r) {
			this.l = l;
			this.r = r;
			min = -1;
			if (r - l > 1) {
				int mid = (l + r) >> 1;
				left = new Node(l, mid);
				right = new Node(mid, r);
			}
		}

		void set(int pos, int x) {
			if (l == pos && pos + 1 == r) {
				min = x;
				return;
			}
			(pos < left.r ? left : right).set(pos, x);
			min = Math.min(left.min, right.min);
		}

		int get(int ql, int qr) {
			if (ql >= r || l >= qr) {
				return Integer.MAX_VALUE;
			}
			if (ql <= l && r <= qr) {
				return min;
			}
			return Math.min(left.get(ql, qr), right.get(ql, qr));
		}

	}

	boolean[] go(Rook[] rs, Query[] qs, int size) {
		Node root = new Node(0, size);
		boolean[] ret = new boolean[qs.length];
		for (int i = 0, j = 0; i < qs.length; i++) {
			while (j < rs.length && rs[j].x <= qs[i].x2) {
				root.set(rs[j].y, rs[j].x);
				j++;
			}
			int val = root.get(qs[i].y1, qs[i].y2 + 1);
			ret[qs[i].id] = val >= qs[i].x1;
		}
		return ret;
	}

	void solve() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int k = nextInt();
		int q = nextInt();
		Rook[] rx = new Rook[k];
		Rook[] ry = new Rook[k];
		for (int i = 0; i < k; i++) {
			int x1 = nextInt() - 1;
			int y1 = nextInt() - 1;
			rx[i] = new Rook(x1, y1);
			ry[i] = new Rook(y1, x1);
		}
		Arrays.sort(rx, Rook.byX);
		Arrays.sort(ry, Rook.byX);

		Query[] qx = new Query[q];
		Query[] qy = new Query[q];
		for (int i = 0; i < q; i++) {
			int x1 = nextInt() - 1;
			int y1 = nextInt() - 1;
			int x2 = nextInt() - 1;
			int y2 = nextInt() - 1;
			qx[i] = new Query(x1, y1, x2, y2, i);
			qy[i] = new Query(y1, x1, y2, x2, i);
		}
		Arrays.sort(qx, Query.byX2);
		Arrays.sort(qy, Query.byX2);

		boolean[] ansX = go(rx, qx, m);
		boolean[] ansY = go(ry, qy, n);

		for (int i = 0; i < q; i++) {
			out.println(ansX[i] || ansY[i] ? "YES" : "NO");
		}
	}

	E() throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

	public static void main(String[] args) throws IOException {
		new E();
	}

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return null;
			}
		}
		return st.nextToken();
	}

	String nextString() {
		try {
			return br.readLine();
		} catch (IOException e) {
			eof = true;
			return null;
		}
	}

	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}
}


import java.io.*;
import static java.lang.Math.*;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.function.*;
import java.lang.*;

public class Main {
    final static boolean debug = false;
    final static String fileName = "";
    final static boolean useFiles = false;

    public static void main(String[] args) throws FileNotFoundException {
        long start;
        if (debug)
            start = System.nanoTime();
        InputStream inputStream;
        OutputStream outputStream;
        if (useFiles) {
            inputStream = new FileInputStream(fileName + ".in");
            outputStream = new FileOutputStream(fileName + ".out");
        } else {
            inputStream = System.in;
            outputStream = System.out;
        }
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task(in, out);
        solver.solve();
        if(debug)
            out.println((System.nanoTime() - start) / 1e+9);
        out.close();
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public double nextDouble(){
        return Double.parseDouble(next());
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public long nextLong(){
        return Long.parseLong(next());
    }

    public byte nextByte(){
        return Byte.parseByte(next());
    }
}

class P{
    char A, B;
    P(char a, char b){
        if (a < b){
            A = a;
            B = b;
        }
        else{
            A = b;
            B = a;
        }
    }
    boolean equals(P r){
        return r.A == A && r.B == B;
    }
}

class Rook{
    int X, Y;
    Rook(int x, int y){
        X = x;
        Y = y;
    }
}

class Query{
    int X1, X2, Y1, Y2;
    int Id;
    Query(int x1, int y1, int x2, int y2, int id){
        X1 = x1;
        X2 = x2;
        Y1 = y1;
        Y2 = y2;
        Id = id;
    }
}

class Task {
    public void solve() {
        int n = in.nextInt();
        int m = in.nextInt();
        int k = in.nextInt();
        int q = in.nextInt();
        Rook[] rooks = new Rook[k];
        for (int i = 0; i < k; i++) {
            rooks[i] = new Rook(in.nextInt() - 1, in.nextInt() - 1);
        }
        Query[] queries = new Query[q];
        for (int i = 0; i < q; i++) {
            queries[i] = new Query(in.nextInt() - 1, in.nextInt() - 1, in.nextInt() - 1, in.nextInt() - 1, i);
        }
        boolean[] x = doIt(n, m, queries, rooks);
        for (Rook rook : rooks) {
            int t = rook.X;
            rook.X = rook.Y;
            rook.Y = t;
        }
        for (Query query : queries) {
            int t = query.X1;
            query.X1 = query.Y1;
            query.Y1 = t;

            t = query.X2;
            query.X2 = query.Y2;
            query.Y2 = t;
        }
        boolean[] y = doIt(m, n, queries, rooks);
        for (int i = 0; i < queries.length; i++) {
            out.println(x[i] || y[i] ? "YES" : "NO");
        }
    }

    boolean[] doIt(int n, int m, Query[] queries, Rook[] rooks) {
        ArrayList<Query>[] queriesByY = new ArrayList[m];
        for (int i = 0; i < m; i++) {
            queriesByY[i] = new ArrayList<>();
        }
        for (Query query : queries) {
            queriesByY[query.Y1].add(query);
        }

        int[] position = new int[n];
        ArrayList<Rook>[] byX = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            byX[i] = new ArrayList<>();
        }
        for (Rook rook : rooks) {
            byX[rook.X].add(rook);
        }
        for (int x = 0; x < n; x++) {
            Collections.sort(byX[x], new Comparator<Rook>() {
                @Override
                public int compare(Rook o1, Rook o2) {
                    return o1.Y - o2.Y;
                }
            });
        }

        ArrayList<Rook>[] byY = new ArrayList[m];
        for (int i = 0; i < m; i++) {
            byY[i] = new ArrayList<>();
        }
        for (Rook rook : rooks) {
            byY[rook.Y].add(rook);
        }
        boolean[] result = new boolean[queries.length];
        BinaryOperatorSegmentTree tree = new BinaryOperatorSegmentTree(n, Math::max);
        for (int x = 0; x < n; x++) {
            if (byX[x].size() == 0) {
                tree.set(x, m);
            } else {
                tree.set(x, byX[x].get(0).Y);
            }
        }
        for (int y = 0; y < m; y++) {
            for (Query q : queriesByY[y]) {
                result[q.Id] = tree.get(q.X1, q.X2) <= q.Y2;
            }
            for (Rook rook : byY[y]) {
                if (position[rook.X] >= byX[rook.X].size() - 1)
                    tree.set(rook.X, m);
                else {
                    position[rook.X]++;
                    tree.set(rook.X, byX[rook.X].get(position[rook.X]).Y);
                }
            }
        }
        return result;
    }

    private InputReader in;
    private PrintWriter out;

    Task(InputReader in, PrintWriter out) {
        this.in = in;
        this.out = out;
    }
}