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

public class snow_bm {
	FastScanner in;
	PrintWriter out;

	class Point implements Comparable<Point> {
		long x, y;

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

		@Override
		public int compareTo(Point o) {
			if (y == o.y)
				return Long.compare(x, o.x);
			return Long.compare(y, o.y);
		}

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

	}

	Point readPoint() {
		return new Point(in.nextInt(), in.nextInt());
	}

	class Event implements Comparable<Event> {
		int type;
		double time;

		public Event(int type, double time) {
			super();
			this.type = type;
			this.time = time;
		}

		@Override
		public int compareTo(Event o) {
			return Double.compare(time, o.time);
		}

	}

	final double eps = 1e-9;

	Double intersect(Point A, Point B, Point C, Point D) {
		// line AB with segment [CD]
		double a1 = A.y - B.y;
		double b1 = B.x - A.x;
		double c1 = -(a1 * A.x + b1 * A.y);
		double a2 = C.y - D.y;
		double b2 = D.x - C.x;
		double c2 = -(a2 * C.x + b2 * C.y);
		double zn = a1 * b2 - a2 * b1;
		if (Math.abs(zn) < eps) {
			return null;
		}
		double x = (-c1 * b2 + c2 * b1) / zn;
		double y = (-c2 * a1 + c1 * a2) / zn;
		// if (Math.abs(a1 * x + b1 * y + c1) > eps)
		// throw new AssertionError();
		// if (Math.abs(a2 * x + b2 * y + c2) > eps)
		// throw new AssertionError();
		if (x < Math.min(C.x, D.x) - eps || x > Math.max(C.x, D.x) + eps)
			return null;
		if (y < Math.min(C.y, D.y) - eps || y > Math.max(C.y, D.y) + eps)
			return null;
		double dx = B.x - A.x;
		double dy = B.y - A.y;
		double dist = Math.sqrt(dx * dx + dy * dy);
		return ((x - A.x) * (B.x - A.x) + (y - A.y) * (B.y - A.y)) / dist;
	}

	final int MAGIC = 2;

	int findPtLeft(Polygon a, Point A, Point B, int[] ptLeftArr, int MAGIC,
			int mul) {
		int bestPtLeft = ptLeftArr[0];
		for (int it = 0; it < ptLeftArr.length; it++)
			for (int i = -MAGIC; i <= MAGIC; i++) {
				int id = ((i + a.length() + ptLeftArr[it]) % a.length() + a
						.length()) % a.length();
				Point p = a.get(id);
				long val = vectMul2(A, B, p);
				if (mul == 1 && val >= vectMul2(A, B, a.get(bestPtLeft))
						|| mul == -1
						&& val <= vectMul2(A, B, a.get(bestPtLeft))) {
					bestPtLeft = id;
				}
			}
		return bestPtLeft;
	}

	double[] intersect(Polygon a, Point A, Point B, int ptLeft, int ptRight) {
		{
			int bestPtLeft = findPtLeft(a, A, B, new int[] { ptLeft, ptRight },
					MAGIC, 1);
			int bestPtRight = findPtLeft(a, A, B,
					new int[] { ptLeft, ptRight }, MAGIC, -1);
			if (bestPtLeft < bestPtRight) {
				ptLeft = bestPtLeft;
				ptRight = bestPtRight;
			} else {
				ptLeft = bestPtRight;
				ptRight = bestPtLeft;
			}
		}
		double min = Double.MAX_VALUE / 2, max = -Double.MAX_VALUE / 2;
		{
			int left = ptLeft, right = ptRight + 1;
			int signLeft = vectMul(A, B, a.get(ptLeft));
			while (right - left > 1) {
				int mid = (left + right) >>> 1;
				if (vectMul(A, B, a.get(mid)) == signLeft) {
					left = mid;
				} else {
					right = mid;
				}
			}
			Double x = intersect(A, B, a.get(left),
					a.get((left + 1) % a.length()));
			if (x != null) {
				min = Math.min(min, x);
				max = Math.max(max, x);
			}
		}
		{
			int left = ptRight, right = a.length() + ptLeft;
			int signLeft = vectMul(A, B, a.get(ptRight));
			while (right - left > 1) {
				int mid = (left + right) >>> 1;
				if (vectMul(A, B, a.get(mid % a.length())) == signLeft) {
					left = mid;
				} else {
					right = mid;
				}
			}
			Double x = intersect(A, B, a.get(left % a.length()),
					a.get((left + 1) % a.length()));
			if (x != null) {
				min = Math.min(min, x);
				max = Math.max(max, x);
			}
		}

		if (min <= max) {
			return new double[] { min, max };
		}
		return null;
	}

	int findClosest(int dx, int dy, Polygon a, int mul, int midPoint) {
		if (mul == 1) {
			int left = -1, right = midPoint;
			while (right - left > 1) {
				int mid = (left + right) >>> 1;
				long rx = a.get(mid + 1).x - a.get(mid).x;
				long ry = a.get(mid + 1).y - a.get(mid).y;
				long val = rx * dy - ry * dx;
				if (val < 0) {
					right = mid;
				} else {
					left = mid;
				}
			}
			return right;
		} else {
			int left = midPoint - 1, right = a.length() - 1;
			while (right - left > 1) {
				int mid = (left + right) >>> 1;
				long rx = a.get(mid + 1).x - a.get(mid).x;
				long ry = a.get(mid + 1).y - a.get(mid).y;
				long val = rx * dy - ry * dx;
				if (val > 0) {
					right = mid;
				} else {
					left = mid;
				}
			}
			return right;
		}
	}

	int vectMul(Point a, Point b, Point c) {
		return Long.signum((b.x - a.x) * 1L * (c.y - a.y) - (b.y - a.y) * 1L
				* (c.x - a.x));
	}

	long vectMul2(Point a, Point b, Point c) {
		return ((b.x - a.x) * 1L * (c.y - a.y) - (b.y - a.y) * 1L * (c.x - a.x));
	}

	boolean isConvex(Point[] a) {
		for (int i = 0; i < a.length; i++) {
			if (vectMul(a[i], a[(i + 1) % a.length], a[(i + 2) % a.length]) < 0)
				return false;
		}
		return true;
	}

	class Polygon {
		Point[] a;
		boolean norm;

		Point res = new Point(0, 0);
		int allX, allY;
		int fromI, toI;
		int addXI, addYI;

		Polygon(Point[] pts) {
			a = pts;
			norm = true;
		}

		int length() {
			return a.length + (norm ? 0 : 2);
		}

		Point get(int id) {
			if (norm) {
				res.x = a[id].x + allX;
				res.y = a[id].y + allY;
			} else {
				if (id <= fromI) {
					res.x = a[id].x + allX;
					res.y = a[id].y + allY;
				} else {
					if (id <= toI + 1) {
						res.x = a[id - 1].x + allX + addXI;
						res.y = a[id - 1].y + allY + addYI;
					} else {
						res.x = a[id - 2].x + allX;
						res.y = a[id - 2].y + allY;
					}
				}
			}
			return new Point(res.x, res.y);
		}

		@Override
		public String toString() {
			String s = "";
			for (int i = 0; i < length(); i++) {
				s += "(" + get(i).x + " " + get(i).y + ")";
				if (i != length() - 1)
					s += ", ";
			}
			return s;
		}

	}

	void solve() {
		Point A = readPoint(), B = readPoint();
		int n = in.nextInt();
		Point[] a = new Point[n];
		for (int i = 0; i < n; i++) {
			a[i] = readPoint();
		}
		if (!isConvex(a))
			throw new AssertionError();
		int m = in.nextInt();
		int[] dx = new int[m];
		int[] dy = new int[m];
		for (int i = 0; i < m; i++) {
			dx[i] = in.nextInt();
			dy[i] = in.nextInt();
		}
		int first = 0;
		for (int i = 1; i < n; i++) {
			if (a[i].compareTo(a[first]) < 0) {
				first = i;
			}
		}
		{
			Point[] tmp = new Point[n + 1];
			for (int i = 0; i < n; i++) {
				tmp[i] = a[(first + i) % a.length];
			}
			tmp[n] = new Point(tmp[0].x, tmp[0].y);
			a = tmp;
			n++;
		}
		ArrayList<Event> allEvents = new ArrayList<>();

		Polygon polygon = new Polygon(a);

		int midPoint = a.length - 1;
		for (int i = 0; i < a.length - 1; i++) {
			long dx1 = a[i + 1].x - a[i].x;
			long dy1 = a[i + 1].y - a[i].y;
			if (dy1 < 0 || (dy1 == 0 && dx1 < 0)) {
				midPoint = i;
				break;
			}
		}

		int dx2 = (int) (B.x - A.x), dy2 = (int) (B.y - A.y);
		if (dy2 < 0 || (dy2 == 0 && dx2 < 0)) {
			dx2 *= -1;
			dy2 *= -1;
		}
		int ptLeft = findPtLeft(polygon, A, B, new int[]{0}, polygon.length(), 1);
		int ptRight = findPtLeft(polygon, A, B, new int[]{0}, polygon.length(), -1);

		if (ptLeft > ptRight) {
			int tmp = ptLeft;
			ptLeft = ptRight;
			ptRight = tmp;
		}

		for (int i = -1; i < m; i++) {
			int curX = polygon.allX, curY = polygon.allY;
			if (i != -1) {
				int dx1 = dx[i], dy1 = dy[i];
				boolean moveAll = false;
				if (dy1 < 0 || (dy1 == 0 && dx1 < 0)) {
					dx1 *= -1;
					dy1 *= -1;
					moveAll = true;
				}
				polygon.norm = true;
				int id1 = findClosest(dx1, dy1, polygon, 1, midPoint);
				int id2 = findClosest(dx1, dy1, polygon, -1, midPoint);
				if (id1 > id2) {
					int tmp = id1;
					id1 = id2;
					id2 = tmp;
				}
				polygon.fromI = id1;
				polygon.toI = id2;
				polygon.addXI = dx1;
				polygon.addYI = dy1;
				polygon.norm = false;
				if (moveAll) {
					polygon.allX += dx[i];
					polygon.allY += dy[i];
				}
			}
			double[] x = intersect(polygon, A, B, ptLeft, ptRight);
			if (x != null) {
				allEvents.add(new Event(1, x[0]));
				allEvents.add(new Event(-1, x[1]));
			}
			if (i != -1) {
				polygon.allX = curX + dx[i];
				polygon.allY = curY + dy[i];
			}

		}

		Collections.sort(allEvents);
		double result = 0;
		double lastTime = 0;
		int cur = 0;
		for (Event e : allEvents) {
			cur += e.type;
			if (e.type != 1 || cur != 1) {
				result += e.time - lastTime;
			}
			lastTime = e.time;
		}
		out.println(result);
	}

	void run() {
		try {
			in = new FastScanner(new File("snow.in"));
			out = new PrintWriter(new File("snow.out"));

			solve();

			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	void runIO() {

		in = new FastScanner(System.in);
		out = new PrintWriter(System.out);

		solve();

		out.close();
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

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

		public FastScanner(InputStream f) {
			br = new BufferedReader(new InputStreamReader(f));
		}

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

		boolean hasMoreTokens() {
			while (st == null || !st.hasMoreTokens()) {
				String s = null;
				try {
					s = br.readLine();
				} catch (IOException e) {
					e.printStackTrace();
				}
				if (s == null)
					return false;
				st = new StringTokenizer(s);
			}
			return true;
		}

		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 snow_bm().run();
	}
}