/* paiza POH! vol.2
* result:
* http://p...content-available-to-author-only...a.jp/poh/paizen/result/ae22de69aa40d92d7f9a4b395dc2649d
* author: Leonardone @ NEETSDKASU
*/
import java.util.*;
import java.lang.*;
import java.lang.ref.*;
import java.io.*;
class Main
{
{
String[] hw
= in.
readLine().
split(" "); int H
= Integer.
parseInt(hw
[0]); // ホーム画面縦の区画数 int W
= Integer.
parseInt(hw
[1]); // ホーム画面横の区画数
int[][] home = new int[H][W];
for (int y = 0; y < H; y++)
{
for (int x = 0; x < W; x++)
{
home[y][x] = (int)(line.charAt(x) - '0');
}
}
int N
= Integer.
parseInt(in.
readLine()); // ウィジェット数
WidgetTree tree = new WidgetTree();
Set<Widget> set = new HashSet<Widget>(N);
Queue<Widget> queue = new ArrayDeque<Widget>(N);
for (int i = 0; i < N; i++)
{
String[] st
= in.
readLine().
split(" "); int s
= Integer.
parseInt(st
[0]); // ウィジェットの縦サイズ int t
= Integer.
parseInt(st
[1]); // ウィジェットの横サイズ
Widget widget = Widget.getWidget(s, t);
if (set.add(widget))
{
tree.add(widget);
}
queue.offer(widget);
}
tree.calc(home);
for (Widget widget : queue)
{
System.
out.
println(widget.
getAnswer()); }
} // end of main(String[])
}
class Widget
{
private static Widget[] pool = new Widget[90604];
public static Widget getWidget(int s, int t)
{
int index = s * 301 + t;
if (pool[index] == null)
{
pool[index] = new Widget(s, t);
}
return pool[index];
}
private final int s;
private final int t;
private int answer = 0;
private Widget(int s, int t)
{
this.s = s;
this.t = t;
}
public int getS()
{
return s;
}
public int getT()
{
return t;
}
public int getAnswer()
{
return answer;
}
public int setAnswer(int answer)
{
this.answer = answer;
return answer;
}
@Override
public int hashCode()
{
return s * 301 + t;
}
@Override
public boolean equals
(Object obj
) {
if (this == obj) return true;
if (obj == null) return false;
if (this.getClass().equals(obj.getClass()) == false) return false;
Widget widget = (Widget)obj;
return this.s == widget.s && this.t == widget.t;
}
@Override
{
return "[" + s + "," + t + "]";
}
public enum Extend
{
S_PARENT, S_CHILD, T_PARENT, T_CHILD,
SAME, IMPOSSIBLE, PRE_T_CHILD, PRE_S_CHILD,
PRE_PARENT
}
public Extend getExtend(Widget widget)
{
if (this.s == widget.s && this.t == widget.t)
{
return Extend.SAME;
}
if (this.s == widget.s)
{
if (this.t < widget.t)
{
return Extend.T_CHILD;
}
return Extend.T_PARENT;
}
if (this.t == widget.t)
{
if (this.s < widget.s)
{
return Extend.S_CHILD;
}
return Extend.S_PARENT;
}
if (this.s < widget.s && this.t < widget.t)
{
if (widget.s < widget.t)
{
return Extend.PRE_T_CHILD;
}
return Extend.PRE_S_CHILD;
}
if (this.s > widget.s && this.t > widget.t)
{
return Extend.PRE_PARENT;
}
return Extend.IMPOSSIBLE;
}
}
class WidgetTree
{
private class Node
{
final Widget widget;
WeakReference<Node> t_parent = null;
WeakReference<Node> s_parent = null;
Node t_child = null;
Node s_child = null;
Queue<Node> pre_s_child = new ArrayDeque<Node>();
Queue<Node> pre_t_child = new ArrayDeque<Node>();
Node(Widget widget)
{
this.widget = widget;
}
@Override
{
return "<" + widget + ";" + t_child
+ ";" + s_child + ";("
+ pre_t_child + ");(" + pre_s_child + ")>";
}
}
private Node root = new Node(Widget.getWidget(1,1));
@Override
{
return root.toString();
}
private enum Family { T_FAMILY, S_FAMILY }
private boolean setFamily(Node parent, Node child, Family family)
{
if (parent == null || child == null || family == null)
{
return false;
}
switch (family)
{
case T_FAMILY:
parent.t_child = child;
child.t_parent = new WeakReference<Node>(parent);
break;
case S_FAMILY:
parent.s_child = child;
child.s_parent = new WeakReference<Node>(parent);
break;
default:
return false;
}
return true;
}
private Node joint(Node node1, Node node2)
{
Node temp = null, temp2 = null, temp3 = null;
int n;
Widget.Extend e = node1.widget.getExtend(node2.widget);
switch (e)
{
case T_PARENT:
{
if (node2.t_child != null)
{
temp = joint(node2.t_child, node1);
setFamily(node2, temp, Family.T_FAMILY);
}
else
{
setFamily(node2, node1, Family.T_FAMILY);
}
n = node2.pre_t_child.size();
for (int i = 0; i < n; i++)
{
temp2 = node2.pre_t_child.poll();
temp3 = joint(node2.t_child, temp2);
if (temp3 == null)
{
node2.pre_t_child.offer(temp2);
}
else
{
setFamily(node2, temp3, Family.T_FAMILY);
}
}
return node2;
}
case S_PARENT:
{
if (node2.s_child != null)
{
temp = joint(node2.s_child, node1);
setFamily(node2, temp, Family.S_FAMILY);
}
else
{
setFamily(node2, node1, Family.S_FAMILY);
}
n = node2.pre_s_child.size();
for (int i = 0; i < n; i++)
{
temp2 = node2.pre_s_child.poll();
temp3 = joint(node2.s_child, temp2);
if (temp3 == null)
{
node2.pre_s_child.offer(temp2);
}
else
{
setFamily(node2, temp3, Family.S_FAMILY);
}
}
return node2;
}
case T_CHILD:
case S_CHILD:
{
return joint(node2, node1);
}
case PRE_S_CHILD:
{
if (node1.s_child != null)
{
temp = joint(node1.s_child, node2);
setFamily(node1, temp, Family.S_FAMILY);
}
if (temp == null)
{
if (node1.pre_s_child.isEmpty())
{
node1.pre_s_child.offer(node2);
}
else
{
n = node1.pre_s_child.size();
for (int i = 0; i < n; i++)
{
temp2 = node1.pre_s_child.poll();
temp3 = joint(temp2, node2);
if (temp3 != null)
{
node1.pre_s_child.offer(temp3);
break;
}
node1.pre_s_child.offer(temp2);
}
if (temp3 == null)
{
node1.pre_s_child.offer(node2);
}
}
}
return node1;
}
case PRE_T_CHILD:
{
if (node1.t_child != null)
{
temp = joint(node1.t_child, node2);
setFamily(node1, temp, Family.T_FAMILY);
}
if (temp == null)
{
if (node1.pre_t_child.isEmpty())
{
node1.pre_t_child.offer(node2);
}
else
{
n = node1.pre_t_child.size();
for (int i = 0; i < n; i++)
{
temp2 = node1.pre_t_child.poll();
temp3 = joint(temp2, node2);
if (temp3 != null)
{
node1.pre_t_child.offer(temp3);
break;
}
else
{
node1.pre_t_child.offer(temp2);
}
}
if (temp3 == null)
{
node1.pre_t_child.offer(node2);
}
}
}
return node1;
}
case SAME:
{
return node1;
}
case PRE_PARENT:
case IMPOSSIBLE:
default:
{
break;
}
}
return null;
}
public boolean add(Widget widget)
{
Node temp = joint(root, new Node(widget));
if (temp == null)
{
return false;
}
root = temp;
return true;
}
private void calc(Node parent, Node child, int[][]array)
{
calc(child, parent.widget.getS(), parent.widget.getT(), array);
}
private void calc(Node node, int s, int t, int[][] array)
{
if (node == null)
{
return;
}
int ds = node.widget.getS() - s;
int dt = node.widget.getT() - t;
int[][] temp = new int[array.length - ds][array[0].length - dt];
int count = 0;
for (int i = 0; i < temp.length; i++)
{
for (int j = 0; j < temp[0].length; j++)
{
for (int dy = 0; dy <= ds; dy++)
{
for (int dx = 0; dx <= dt; dx++)
{
temp[i][j] += array[i + dy][j + dx];
}
}
if (temp[i][j] == 0)
{
count++;
}
}
}
node.widget.setAnswer(count);
calc(node, node.t_child, temp);
calc(node, node.s_child, temp);
for (Node p : node.pre_t_child)
{
calc(node, p, temp);
}
for (Node p : node.pre_s_child)
{
calc(node, p, temp);
}
}
public void calc(int[][] home)
{
calc(root, 1, 1, home);
}
}