// Arup Guha
// 5/20/2017
// Solution to 2016 South East Regional Division I Problem: Enclosure

import java.util.*;
import java.io.*;

public class enclosure {

	public static int n;
	public static int k;
	public static pt[] mine;

	public static long[] rotSum; // Stores cumulative sums.

	public static void main(String[] args) throws Exception {

		// Read in the points.
		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());
		n = Integer.parseInt(tok.nextToken());
		k = Integer.parseInt(tok.nextToken());

		pt[] pts = new pt[k];
		for (int i=0; i<k; i++) {
			tok = new StringTokenizer(stdin.readLine());
			long x = Long.parseLong(tok.nextToken());
			long y = Long.parseLong(tok.nextToken());
			pts[i] = new pt(x, y);
		}

		// Set the reference point.
		int refIndex = getIndexMin(pts, k);
		pt.refX = pts[refIndex].x;
		pt.refY = pts[refIndex].y;

		// Output solution.
		ArrayList<pt> myhull = grahamScan(pts, k);
		Collections.reverse(myhull);

		// Get the area of the regular convex hull of points.
		long hull = doubleArea(myhull);

		long res = hull;

		// Try adding each point they ask us to try to our hull and see how much bigger the hull gets.
		for (int i=0; i<n-k; i++) {

			// Get the point.
			tok = new StringTokenizer(stdin.readLine());
			long x = Long.parseLong(tok.nextToken());
			long y = Long.parseLong(tok.nextToken());
			pt add = new pt(x, y);

			// Skip points inside my area.
			if (in(myhull,add)) continue;

			// Get points of "tangency"
			int[] bound = getTangent(myhull, add);

			// Calculate added area with this point and see if it updates our answer.
			long extra = getAdded(myhull, bound, add);
			res = Math.max(res, hull+extra);
		}

		// Our final result.
		System.out.print(res/2);
		if (res%2 == 0) System.out.println(".0");
		else			System.out.println(".5");
	}

	// Runs a binary search for greatest or least angle in between low and high from the newly added point.
	public static int binSearch(ArrayList<pt> pts, pt add, int low, int high, boolean gtZero) {

		// Run a ternary search a couple iterations short
		while (low < high-3) {

			// Get our bounds and run the cross product check.
			int left = (2*low+high)/3;
			int right = (low+2*high)/3;
			pt tempv1 = add.getVect(pts.get(left));
			pt tempv2 = add.getVect(pts.get(right));
			boolean comp = gtZero ? tempv1.crossMag(tempv2) > 0 : tempv1.crossMag(tempv2) < 0;

			// Here is how it's safe to move low or high.
			if (comp)
				low = left;
			else
				high = right;
		}

		// Just sweep through what's left and store the best answer.
		int res = low;
		pt ref = add.getVect(pts.get(low));
		for (int i=low+1; i<=high; i++) {
			pt temp = add.getVect(pts.get(i));
			boolean comp = gtZero ? ref.crossMag(temp) > 0 : ref.crossMag(temp) < 0;
			if (comp) {
				res = i;
				ref = temp;
			}
		}

		return res;
	}

	// Returns an array of size 2 storing the two points of "tangency" which will allow us to calculate the new convex hull.
	public static int[] getTangent(ArrayList<pt> pts, pt add) {

		int[] bound = new int[2];
		int n = pts.size();
		pt toZero = add.getVect(pts.get(0));
		pt toOne = add.getVect(pts.get(1));
		pt toLast = add.getVect(pts.get(n-1));

		// 0 is a boundary on top
		if (toZero.crossMag(toOne) > 0 && toZero.crossMag(toLast) > 0) {
			bound[0] = 0;
			bound[1] = binSearch(pts, add, 1, n-1, true);
		}

		// 0 is other boundary
		else if (toZero.crossMag(toOne) < 0 && toZero.crossMag(toLast) < 0) {
			bound[0] = 0;
			bound[1] = binSearch(pts, add, 1, n-1, false);
		}

		// 0 is not a boundary.
		else {

			//Left hand turn for vector new->0 to vectore new->1.
			if (toZero.crossMag(toOne) < 0) {

				// want "max" i such that toZero.crossMag(i) < 0
				int low = 1, high = n-1;
				while (low < high) {
					int mid = (low+high+1)/2;
					pt tmpV = add.getVect(pts.get(mid));
					long tmp = toZero.crossMag(tmpV);
					if (tmp < 0)
						low = mid;
					else
						high = mid-1;
				}

				// One we figure out low, we can binary search both sides.
				bound[0] = binSearch(pts, add, 1, low, false);
				bound[1] = binSearch(pts, add, low+1, n-1, true);
			}

			// Opposite case; right hand turn...
			else {

				// want "max" i such that toZero.crossMag(i) > 0
				int low = 1, high = n-1;
				while (low < high) {
					int mid = (low+high+1)/2;
					pt tmpV = add.getVect(pts.get(mid));
					long tmp = toZero.crossMag(tmpV);
					if (tmp > 0)
						low = mid;
					else
						high = mid-1;
				}

				bound[0] = binSearch(pts, add, 1, low, true);
				bound[1] = binSearch(pts, add, low+1, n-1, false);
			}
		}

		return bound;
	}

	public static boolean in(ArrayList<pt> pts, pt add) {

		double toZero = add.angleTo(pts.get(0));
		double toOne = add.angleTo(pts.get(1));

		// This is a simple case based on how I form my convex hull.
		if (withinPi(toOne, toZero)) return false;

		// Set up binary search to find max angle less than 180 with add->pts[0].
		int low = 1, high = pts.size()-1;

		// Run binary search.
		while (low < high) {

			int mid = (low+high+1)/2;

			double toMid = add.angleTo(pts.get(mid));

			if (withinPi(toZero, toMid))
				low = mid;
			else
				high = mid-1;
		}

		// If all pts are within pi, then add isn't in the hull.
		if (low == pts.size()-1) return false;

		// As long as the angle between the last point before we hit pi to the next is within pi, we are good.
		return withinPi(add.angleTo(pts.get(low)), add.angleTo(pts.get(low+1)));
	}

	public static boolean withinPi(double start, double end) {

		// Usual way.
		if (end > start && end-start < Math.PI) return true;

		// Opposite way when end wrapped around with atan2.
		if (end + Math.PI < start) return true;

		return false;
	}

	public static long getAdded(ArrayList<pt> pts, int[] bound, pt add) {

		for (int i=0; i<bound.length; i++) bound[i] = bound[i]%pts.size();

		pt v1 = add.getVect(pts.get(bound[0]));
		pt v2 = add.getVect(pts.get(bound[1]));

		long area = v1.crossMag(v2);

		// Vectors are in counter-clockwise order, as we want.
		if (area < 0) {

			// My two bounds are in order on the old hull but my area is negative.
			if (bound[0] < bound[1]) {
				long sub = rotSum[bound[1]] - rotSum[bound[0]];
				long plus = pts.get(bound[0]).x*add.y - pts.get(bound[0]).y*add.x + add.x*pts.get(bound[1]).y - add.y*pts.get(bound[1]).x;
				return plus-sub;
			}

			// My bounds are in opposite order and the area is negative.
			else {
				long plus = pts.get(bound[0]).x*add.y - pts.get(bound[0]).y*add.x + add.x*pts.get(bound[1]).y - add.y*pts.get(bound[1]).x;
				return rotSum[bound[0]] - rotSum[bound[1]] + plus - rotSum[pts.size()];
			}

		}

		// Area is positive so clockwise turn.
		else {

			// Bounds are in order.
			if (bound[0] < bound[1]) {
				long circle = rotSum[bound[1]] - rotSum[bound[0]];
				long plus = pts.get(bound[1]).x*add.y - pts.get(bound[1]).y*add.x + add.x*pts.get(bound[0]).y - add.y*pts.get(bound[0]).x;
				return plus + circle - rotSum[pts.size()];
			}

			// Bounds are out of order.
			else {
				long plus = pts.get(bound[1]).x*add.y - pts.get(bound[1]).y*add.x + add.x*pts.get(bound[0]).y - add.y*pts.get(bound[0]).x;
				return plus - (rotSum[bound[0]] - rotSum[bound[1]]);
			}
		}
	}

	// Does usual area formula...returns twice the area.
	public static long doubleArea(ArrayList<pt> pts) {
		long res = 0;
		rotSum = new long[pts.size()+1];
		for (int i=0; i<pts.size(); i++) {
			int j = (i+1)%pts.size();
			res += (pts.get(i).x*pts.get(j).y-pts.get(j).x*pts.get(i).y);
			rotSum[i+1] = res;
		}
		return Math.abs(res);
	}

	// Returns the point in pts with minimum y breaking tie by minimum x.
	public static int getIndexMin(pt[] pts, int n) {
		int res = 0;
		for (int i=1; i<n; i++)
			if (pts[i].y < pts[res].y || (pts[i].y == pts[res].y && pts[i].x < pts[res].x))
				res = i;
		return res;
	}

	public static ArrayList<pt> grahamScan(pt[] pts, int n) {

		// Sort the points by angle with reference point.
		Arrays.sort(pts);

		// Push first two points on.
		Stack<pt> myStack = new Stack<pt>();
		myStack.push(pts[0]);
		myStack.push(pts[1]);

		// Go through the rest of the points.
		for (int i=2; i<n; i++) {

			// Get last three pts.
			pt cur = pts[i];
			pt mid = myStack.pop();
			pt prev = myStack.pop();

			// Pop off the left turns.
			while (!prev.isRightTurn(mid, cur)) {
				mid = prev;
				prev = myStack.pop();
			}

			// Push back the last right turn.
			myStack.push(prev);
			myStack.push(mid);
			myStack.push(cur);
		}

		// Pop off pts forming the hull.
		ArrayList<pt> hull = new ArrayList<pt>();
		while (myStack.size() > 0)
			hull.add(myStack.pop());

		// Return.
		return hull;
	}
}

class pt implements Comparable<pt> {

	// Stores reference pt
	public static long refX;
	public static long refY;

	public long x;
	public long y;

	public pt(long myx, long myy) {
		x = myx;
		y = myy;
	}

	// Returns the vector from this to other.
	public pt getVect(pt other) {
		return new pt(other.x-x, other.y-y);
	}

	// Returns the distance between this and other.
	public double dist(pt other) {
		return Math.sqrt((other.x-x)*(other.x-x) + (other.y-y)*(other.y-y));
	}

	// Returns the magnitude ot this cross product other.
	public long crossMag(pt other) {
		return this.x*other.y - other.x*this.y;
	}

	// returns true iff this to mid to next is a right turn (180 degree is considered right turn).
	public boolean isRightTurn(pt mid, pt next) {
		pt v1 = getVect(mid);
		pt v2 = mid.getVect(next);
		return v1.crossMag(v2) > 0; /*** Do > 0 if you don't want collinear pts. ***/
	}

	// Returns true iff this pt is the origin.
	public boolean isZero() {
		return x == 0 && y == 0;
	}

	public double angleTo(pt other) {
		return Math.atan2(other.y-this.y, other.x-this.x);
	}

	public String toString() {
		return "("+x+", "+y+")";
	}

	public int compareTo(pt other) {

		pt myRef = new pt(refX, refY);
		pt v1 = myRef.getVect(this);
		pt v2 = myRef.getVect(other);

		// To avoid 0 issues.
		if (v1.isZero()) return -1;
		if (v2.isZero()) return 1;

		// Angles are different, we are going counter-clockwise here.
		if (v1.crossMag(v2) < 0) return 1;
		if (v1.crossMag(v2) > 0) return -1;

		// This should work, smaller vectors come first.
		if (myRef.dist(v1) < myRef.dist(v2)) return -1;
		return 1;
	}
}