Problem:
Score : 400 points

Problem Statement

We have a grid with H rows and W columns. At first, all cells were painted white.

Snuke painted N of these cells. The i-th ( 1 \leq i \leq N ) cell he painted is the cell at the a_i-th row and b_i-th column.

Compute the following:

For each integer j ( 0 \leq j \leq 9 ), how many subrectangles of size 3×3 of the grid contains exactly j black cells, after Snuke painted N cells?

Constraints

3 \leq H \leq 10^9

3 \leq W \leq 10^9

0 \leq N \leq min(10^5,H×W)

1 \leq a_i \leq H (1 \leq i \leq N)

1 \leq b_i \leq W (1 \leq i \leq N)

(a_i, b_i) \neq (a_j, b_j) (i \neq j)

Input

The input is given from Standard Input in the following format:

H W N
a_1 b_1
:
a_N b_N

Output

Print 10 lines.
The (j+1)-th ( 0 \leq j \leq 9 ) line should contain the number of the subrectangles of size 3×3 of the grid that contains exactly j black cells.

Sample Input 1

4 5 8
1 1
1 4
1 5
2 3
3 1
3 2
3 4
4 4

Sample Output 1

0
0
0
2
4
0
0
0
0
0

There are six subrectangles of size 3×3. Two of them contain three black cells each, and the remaining four contain four black cells each.

Sample Input 2

10 10 20
1 1
1 4
1 9
2 5
3 10
4 2
4 7
5 9
6 4
6 6
6 7
7 1
7 3
7 7
8 1
8 5
8 10
9 2
10 4
10 9

Sample Output 2

4
26
22
10
2
0
0
0
0
0

Sample Input 3

1000000000 1000000000 0

Sample Output 3

999999996000000004
0
0
0
0
0
0
0
0
0

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using static System.Console;
using static System.Math;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using CS_Contest.Graph;
using CS_Contest.Loop;
//using CS_Contest.Utils;
using static Nakov.IO.Cin;
using static CS_Contest.Utils.Utils;

namespace CS_Contest {
	using Li = List<int>;
	using LLi = List<List<int>>;
	using Ll = List<long>;
	using ti3=Tuple<int,int,int>;
	using II=Tuple<int,int>;
	internal class Program {
		private static void Main(string[] args) {
			var sw = new StreamWriter(OpenStandardOutput()) { AutoFlush = false };
			SetOut(sw);
			new Calc().Solve();
			Out.Flush();
		}

		public class Calc {
			public void Solve() {
				int H = NextInt(), W = NextInt(), N = NextInt();
				var dic = new Dictionary<II, long>();

				var d = new[] {0, 1, 2};

				N.REP(i=>
				{
					int ai = NextInt(), bi = NextInt();
					ai--;
					bi--;
					3.REP(j=>
					{
						3.REP(k =>
						{
							var pos = new II(ai - d[j], bi - d[k]);
							if (ai - d[j] < 0 || bi - d[k] < 0 || ai - d[j] >= H - 2 || bi - d[k] >= W - 2) return;
							if (dic.ContainsKey(pos)) dic[pos]++;
							else dic.Add(pos, 1);
						});
					});
				});
				var ans = new long[10];
				foreach (var item in dic) {
					ans[item.Value]++;
				}
				ans[0] = (long)(H - 2) * (long)(W - 2) - ans.Sum();
				ans.WL();

				return;
			}
		}
	}



	

}
namespace Nakov.IO {
	using System;
	using System.Text;
	using System.Globalization;

	public static class Cin {
		public static string NextToken() {
			StringBuilder tokenChars = new StringBuilder();
			bool tokenFinished = false;
			bool skipWhiteSpaceMode = true;
			while (!tokenFinished) {
				int nextChar = Console.Read();
				if (nextChar == -1) {
					tokenFinished = true;
				} else {
					char ch = (char)nextChar;
					if (char.IsWhiteSpace(ch)) {
						if (!skipWhiteSpaceMode) {
							tokenFinished = true;
							if (ch == '\r' && (Environment.NewLine == "\r\n")) {
								Console.Read();
							}
						}
					} else {
						skipWhiteSpaceMode = false;
						tokenChars.Append(ch);
					}
				}
			}

			string token = tokenChars.ToString();
			return token;
		}

		public static int NextInt() {
			string token = Cin.NextToken();
			return int.Parse(token);
		}
		public static long NextLong() {
			string token = Cin.NextToken();
			return long.Parse(token);
		}
		public static double NextDouble(bool acceptAnyDecimalSeparator = true) {
			string token = Cin.NextToken();
			if (acceptAnyDecimalSeparator) {
				token = token.Replace(',', '.');
				double result = double.Parse(token, CultureInfo.InvariantCulture);
				return result;
			} else {
				double result = double.Parse(token);
				return result;
			}
		}
		public static decimal NextDecimal(bool acceptAnyDecimalSeparator = true) {
			string token = Cin.NextToken();
			if (acceptAnyDecimalSeparator) {
				token = token.Replace(',', '.');
				decimal result = decimal.Parse(token, CultureInfo.InvariantCulture);
				return result;
			} else {
				decimal result = decimal.Parse(token);
				return result;
			}
		}

	}
}

namespace CS_Contest.Graph
{
	using Ll=List<long>;
	using Li=List<int>;
	public class BellmanFord : CostGraph {
		public BellmanFord(int size) : base(size) {
		}

		public List<long> Distance { get; set; }

		private bool[] _negative;
		public bool HasCycle => _negative[Size - 1];

		public void Run(int s) {
			Distance = new Ll();
			Size.REP(i => Distance.Add(Inf));
			Distance[s] = 0;
			_negative = new bool[Size];

			(Size - 1).REP(i => Size.REP(j => Adjacency[j].Count.REP(k =>
				{
					var src = Adjacency[j][k];
					if (Distance[src.To] > Distance[j] + src.Cost) Distance[src.To] = Distance[j] + src.Cost;
				}
			)));

			for (int i = 0; i < Size; i++) {
				Size.REP(j => {
					Adjacency[j].Count.REP(k => {
						var src = Adjacency[j][k];
						if (Distance[src.To] > Distance[j] + src.Cost) {
							Distance[src.To] = Distance[j] + src.Cost;
							_negative[src.To] = true;
						}
						if (_negative[j]) _negative[src.To] = true;
					});
				});
			}
		}
	}
	public class CostGraph {
		public struct Edge {
			public int To { get; set; }
			public long Cost { get; set; }


			public Edge(int to, long cost) {
				To = to;
				Cost = cost;
			}

		}

		public int Size { get; set; }
		public List<List<Edge>> Adjacency { get; set; }
		public const long Inf = (long)1e15;

		public CostGraph(int size) {
			Size = size;
			Adjacency = new List<List<Edge>>();
			Size.REP(_ => Adjacency.Add(new List<Edge>()));
		}

		public void Add(int s, int t, long c, bool dir = true) {
			Adjacency[s].Add(new Edge(t, c));
			if (!dir) Adjacency[t].Add(new Edge(s, c));
		}

	}

	/// <summary>
	/// 優先度付きキュー
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class PriorityQueue<T> {
		private readonly List<T> heap;
		private readonly Comparison<T> compare;
		private int size;

		public PriorityQueue() : this(Comparer<T>.Default) {
		}

		public PriorityQueue(IComparer<T> comparer) : this(16, comparer.Compare) {
		}

		public PriorityQueue(Comparison<T> comparison) : this(16, comparison) {
		}

		public PriorityQueue(int capacity, Comparison<T> comparison) {
			this.heap = new List<T>(capacity);
			this.compare = comparison;
		}

		public void Enqueue(T item) {
			this.heap.Add(item);
			var i = size++;
			while (i > 0) {
				var p = (i - 1) >> 1;
				if (compare(this.heap[p], item) <= 0)
					break;
				this.heap[i] = heap[p];
				i = p;
			}
			this.heap[i] = item;
		}

		public T Dequeue() {
			var ret = this.heap[0];
			var x = this.heap[--size];
			var i = 0;
			while ((i << 1) + 1 < size) {
				var a = (i << 1) + 1;
				var b = (i << 1) + 2;
				if (b < size && compare(heap[b], heap[a]) < 0) a = b;
				if (compare(heap[a], x) >= 0)
					break;
				heap[i] = heap[a];
				i = a;
			}
			heap[i] = x;
			heap.RemoveAt(size);
			return ret;
		}

		public T Peek() {
			return heap[0];
		}

		public int Count => size;

		public bool Any() {
			return size > 0;
		}
	}


	public class Dijkstra : CostGraph {
		public Dijkstra(int size) : base(size) { }
		public int[] PreviousNodeList { get; set; }
		public long[] Distance { get; set; }

		public void Run(int s) {
			PreviousNodeList = new int[Size];
			Distance = new long[Size];
			Size.REP(_ => Distance[_] = Inf);

			var pq = new PriorityQueue<Edge>((x, y) => x.Cost.CompareTo(y.Cost));
			Distance[s] = 0;
			pq.Enqueue(new Edge(s, 0));
			while (pq.Any()) {
				var src = pq.Dequeue();
				if (Distance[src.To] < src.Cost) continue;
				for (var i = 0; i < Adjacency[src.To].Count; i++) {
					var tmp = Adjacency[src.To][i];
					var cost = tmp.Cost + src.Cost;
					if (cost >= Distance[tmp.To]) continue;
					Distance[tmp.To] = cost;
					pq.Enqueue(new Edge(tmp.To, cost));
					PreviousNodeList[tmp.To] = src.To;
				}
			}
		}
	}


	public class WarshallFloyd : CostGraph {
		public WarshallFloyd(int size) : base(size) {
		}

		public List<Ll> Run() {
			var rt = new List<Ll>();
			Size.REP(_ => rt.Add(new Ll()));

			Size.REP(i => Size.REP(k => rt[i].Add(i == k ? 0 : Inf)));

			ForeachWith(Adjacency, (i, item) => {
				foreach (var k in item) {
					rt[i][k.To] = k.Cost;
				}
			});

			Size.REP(i => Size.REP(j => Size.REP(k => {
				rt[j][k] = Min(rt[j][k], rt[j][i] + rt[i][k]);
			})));

			return rt;
		}
	}

}

namespace CS_Contest.Loop
{
	public static class Loop
	{
		public static void REP(this int n, Action<int> act) {
			for (var i = 0; i < n; i++) {
				act(i);
			}
		}
	}
}

namespace CS_Contest.Utils
{
	using Li=List<int>;
	using Ll=List<long>;
	public static class Utils
	{
		public static List<T> Repeat<T>(Func<int, T> result, int range) =>
			Enumerable.Range(0, range).Select(result).ToList();

		public static long[,] CombinationTable(int n) {
			var rt = new long[n + 1, n + 1];
			for (var i = 0; i <= n; i++) {
				for (var j = 0; j <= i; j++) {
					if (j == 0 || i == j) rt[i, j] = 1L;
					else rt[i, j] = (rt[i - 1, j - 1] + rt[i - 1, j]);
				}
			}
			return rt;
		}
		public static long ModValue = (long)1e9 + 7;
		public static long INF = long.MaxValue;

		public static long Mod(long x) => x % ModValue;

		public static long ModPow(long x, long n) {
			long tmp = 1; while (n != 0) { if (n % 2 == 1) { tmp = Mod(tmp * x); } x = Mod(x * x); n /= 2; }
			return tmp;
		}

		public static long DivMod(long x, long y) => Mod(x * ModPow(y, (long)(1e9 + 5)));
		public static void Add<T1, T2>(this List<Tuple<T1, T2>> list, T1 t1, T2 t2) => list.Add(new Tuple<T1, T2>(t1, t2));

		public static bool IsPrime(int n) {
			if (n == 2) return true;
			if (n < 2||n%2==0) return false;
			var i = 3;
			int sq = (int)Sqrt(n);
			while (i <= sq) {
				if (n % i == 0) return false;
				i += 2;
			}
			return true;
		}

		public static IEnumerable<int> Primes(int maxnum) {
			yield return 2;
			yield return 3;
			var sieve = new BitArray(maxnum + 1);
			int squareroot = (int)Math.Sqrt(maxnum);
			for (int i = 2; i <= squareroot; i++) {
				if (sieve[i] == false) {
					for (int n = i * 2; n <= maxnum; n += i)
						sieve[n] = true;
				}
				for (var n = i * i + 1; n <= maxnum && n < (i + 1) * (i + 1); n++) {
					if (!sieve[n])
						yield return n;
				}
			}
		}

		public static T Min<T>(params T[] a) where T : IComparable<T> => a.Min();
		public static T Max<T>(params T[] a) where T : IComparable<T> => a.Max();

		public static void WL(this object obj) => WriteLine(obj);
		public static void WL(this string obj) => WriteLine(obj);
		public static void WL<T>(this IEnumerable<T> list) => list.ToList().ForEach(x => x.WL());

		public static Li GetIntList() => ReadLine().Split().Select(int.Parse).ToList();
		public static Ll GetLongList() => ReadLine().Split().Select(long.Parse).ToList();

		public static string StringJoin<T>(this IEnumerable<T> l, string separator = "") => string.Join(separator, l);

		public static void ForeachWith<T>(IEnumerable<T> ie, Action<int, T> act) {
			var i = 0;
			foreach (var item in ie) {
				act(i, item);
				i++;
			}
		}

		public static void Foreach<T>(this IEnumerable<T> ie, Action<T> act) {
			foreach (var item in ie) {
				act(item);
			}
		}


		public static int ManhattanDistance(int x1, int y1, int x2, int y2) => Abs(x2 - x1) + Abs(y2 - y1);

		public static Queue<T> ToQueue<T>(this IEnumerable<T> iEnumerable) {
			var rt = new Queue<T>();
			foreach (var item in iEnumerable) {
				rt.Enqueue(item);
			}
			return rt;
		}
		public static void Swap<T>(ref T x, ref T y) {
			var tmp = x;
			x = y;
			y = tmp;
		}
		public static Dictionary<TKey, int> CountUp<TKey>(this IEnumerable<TKey> l) {
			var dic = new Dictionary<TKey, int>();
			foreach (var item in l) {
				if (dic.ContainsKey(item)) dic[item]++;
				else dic.Add(item, 1);
			}
			return dic;
		}
		public static int Count<T>(this IEnumerable<T> l, T target) => l.Count(x => x.Equals(target));
	}


}