// Arup Guha
// 10/18/2013
// Solution to 2008 MCPC Problem E: Bulletin Board

import java.util.*;

public class e {

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		int n = stdin.nextInt();

		while (n != 0) {

			int W = stdin.nextInt();
			int L = stdin.nextInt();

			rect[] set = new rect[n];

			// Here we keep track of all important x's and y's.
			TreeSet<Integer> xVals = new TreeSet<Integer>();
			TreeSet<Integer> yVals = new TreeSet<Integer>();
			xVals.add(0);
			xVals.add(W);
			yVals.add(0);
			yVals.add(L);

			// Read in rectangles.
			int i, j, k;
			for (i=0; i<n; i++) {
				int x1 = stdin.nextInt();
				int y1 = stdin.nextInt();
				int x2 = stdin.nextInt();
				int y2 = stdin.nextInt();
				set[i] = new rect(x1,y1,x2,y2);

				// Keep track of each distinct x, y.
				xVals.add(x1);
				xVals.add(x2);
				yVals.add(y1);
				yVals.add(y2);
			}

			// Copy x vals into list in sorted oder.
			int[] xList = getList(xVals);
			int[] yList = getList(yVals);
			HashMap<Integer,Integer> xMap = getMap(xList);
			HashMap<Integer,Integer> yMap = getMap(yList);

			// Set up compressed coordinates.
			for (i=0; i<n; i++)
				set[i].setMap(xMap, yMap);

			// Find area not covered at all and all depths.
			int norect = 0;
			int[][] depth = new int[xList.length-1][yList.length-1];

			// Go through each section of the coordinate compressed grid.
			for (i=0; i<xList.length-1; i++) {
				for (j=0; j<yList.length-1; j++) {

					// See if each rectangle is active in this portion of the grid.
					boolean off = true;
					for (k=0; k<n; k++) {
						if (set[k].in(i,j)) {
							off = false;
							depth[i][j]++;
						}
					}

					// Everything was off, so add in this rectangle.
					if (off) norect += ((xList[i+1]-xList[i])*(yList[j+1]-yList[j]));
				}
			}

			// Get max depth.
			int maxD = 0;
			for (i=0; i<depth.length; i++)
				for (j=0; j<depth[0].length; j++)
					if (maxD < depth[i][j])
						maxD = depth[i][j];

			// Now we can find the area in alll places with maximum depth.
			int maxArea = 0;
			for (i=0; i<depth.length; i++)
				for (j=0; j<depth[0].length; j++)
					if (depth[i][j] == maxD)
						maxArea += ((xList[i+1]-xList[i])*(yList[j+1]-yList[j]));

			// All of our results.
			System.out.println(norect+" "+maxD+" "+maxArea);

			n = stdin.nextInt();
		}
	}

	public static HashMap<Integer,Integer> getMap(int[] list) {

		HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
		for (int i=0; i<list.length; i++)
			map.put(list[i], i);

		return map;
	}

	// Return items in t in a sorted array.
	public static int[] getList(TreeSet<Integer> t) {
		int[] list = new int[t.size()];
		int i = 0;
		while (t.size() > 0)
			list[i++] = t.pollFirst();
		return list;
	}
}

class rect {

	public int minX;
	public int minY;
	public int maxX;
	public int maxY;
	public int minXMap;
	public int minYMap;
	public int maxXMap;
	public int maxYMap;

	public rect(int x1, int y1, int x2, int y2) {
		minX = x1;
		minY = y1;
		maxX = x2;
		maxY = y2;
	}

	public boolean in(int mapXLow, int mapYLow) {
		return mapXLow >= minXMap && mapXLow < maxXMap &&
			   mapYLow >= minYMap && mapYLow < maxYMap;
	}

	public void setMap(HashMap<Integer,Integer> xMap, HashMap<Integer,Integer> yMap) {
		minXMap = xMap.get(minX);
		minYMap = yMap.get(minY);
		maxXMap = xMap.get(maxX);
		maxYMap = yMap.get(maxY);
	}
}