/* paiza POH! vol.2
* result:
* http://p...content-available-to-author-only...a.jp/poh/paizen/result/16ee5b809fc9a60cf232532f432464af
* 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);
Widget[] list = new 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]); // ウィジェットの横サイズ
list[i] = Widget.getWidget(s, t);
if (s <= H && t <= W)
{
if (set.add(list[i]))
{
tree.add(list[i]);
}
}
}
tree.calc(H, W, home);
for (Widget widget : list)
{
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;
}
public int childrenCount()
{
return (t_child != null ? 1 : 0)
+ (s_child != null ? 1: 0)
+ pre_s_child.size()
+ pre_t_child.size();
}
@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, int h, int w, boolean nocopy)
{
calc(child, parent.widget.getS(), parent.widget.getT(), array, h, w, nocopy);
}
private void calc(Node node, int s, int t, int[][] array, int h, int w, boolean nocopy)
{
if (node == null)
{
return;
}
int ds = node.widget.getS() - s;
int dt = node.widget.getT() - t;
int hh = h - ds;
int ww = w - dt;
int[][] temp;
if (nocopy)
{
temp = array;
}
else
{
temp = new int[hh][ww];
}
int count = 0;
for (int i = 0; i < hh; i++)
{
for (int j = 0; j < ww; 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);
nocopy = node.childrenCount() < 2;
calc(node, node.t_child, temp, hh, ww, nocopy);
calc(node, node.s_child, temp, hh, ww, nocopy);
for (Node p : node.pre_t_child)
{
calc(node, p, temp, hh, ww, nocopy);
}
for (Node p : node.pre_s_child)
{
calc(node, p, temp, hh, ww, nocopy);
}
}
public void calc(int h, int w, int[][] home)
{
calc(root, 1, 1, home, h, w, false);
}
}