/**/ /*
    题意:问海平面为d时,各个岛屿的income总和
           
    首先要注意d高于格子的高度时,未必被掩了,跟相邻有关。
    方法就是类似最短路的先对所有的点重新标号,得到每个点真正被淹没的时间。 
    用PQ的dijkstra 我用spfa好像有问题,应该我写得有问题
    像数据    33333
            35553
            35153
            35553
            33333
    
    之后就是对查询排序,然后从高到低,看那些格子升出了水面,这些格子可能会和周围的格子练成岛屿,
    这个部分通过并查集来做就好了。
    用map<int, int>来记录大小为first的岛屿有second个,以回答查询。

    细节很多
    如:
        应该合并到较高位置;
        要先查询、每个点高度排序,对每次查询都扫描是否已经合并过就TLE了
    
*/

#include
< cstdio >
#include
< cstring >
#include
< algorithm >
#include
< map >
#include
< vector >
#include
< queue >

using   namespace  std;

const   int  MAXN  =   510 ;

const   int  dx[ 4 ] = {0,0,1,-1} ;
const   int  dy[ 4 ] = {1,-1,0,0} ;

int  R,C,Q;
long   long  ans[ 10010 ];
int  height[MAXN][MAXN];
bool  visit[MAXN][MAXN];
int  fa[MAXN * MAXN],S[MAXN * MAXN];
map
< int , int > mp;

bool  chk( int  x, int  y) {return x>=0&&x<R&&y>=0&&y<C;}

/**/ /*
    计算1的个数 也可以递推
    ones[0]=0
    for(int i=1;i<MAXN*MAXN;i++)
        ones[i]=ones[i>>1]+(i&1);
*/

inline 
int  calc( int  x)
{
    
int tot=0;
    
while(x)tot+=(x&1),x>>=1;
    
return tot;
}

int  find( int  x)
{
    
return fa[x]==x?x:fa[x]=find(fa[x]);
}

void  unit( int  x, int  y)
{    
    x
=find(x),y=find(y);
    
if(x==y)return;
    
if(--mp[S[x]]==0)mp.erase(S[x]);//注意删除掉!
    if(--mp[S[y]]==0)mp.erase(S[y]);
    fa[x]
=y;
    S[y]
+=S[x];
    mp[S[y]]
++;
}

int  main()
{
    
while(~scanf("%d%d",&R,&C))
    
{
        mp.clear();
        memset(visit,
0,sizeof(visit));
        priority_queue
<pair<int,pair<int,int> > >PQ;
        
for(int i=0;i<R;i++)
            
for(int j=0;j<C;j++)
            
{
                scanf(
"%d",&height[i][j]);
                
if(i==R-1||i==0||j==C-1||j==0)
                
{
                    visit[i][j]
=1;
                    PQ.push(make_pair(
-height[i][j],make_pair(i,j)));
                }

            }

        
//dijkstra
        while(!PQ.empty())
        
{
            
int x=PQ.top().second.first,y=PQ.top().second.second;
            PQ.pop();    
            
for(int k=0;k<4;k++)
            
{
                
int xx=x+dx[k],yy=y+dy[k];
                
if(chk(xx,yy)&&!visit[xx][yy])
                
{
                    visit[xx][yy]
=1;//第一次遇到的就是答案了
                    height[xx][yy]=max(height[xx][yy],height[x][y]);
                    PQ.push(make_pair(
-height[xx][yy],make_pair(xx,yy)));
                }

            }

        }


        
/**//*    
            for(int i=0;i<R;i++)
                for(int j=0;j<C;j++)
                {
                    printf("%d%c",height[i][j],j==C-1?'\n':' ');
                }
        
*/


        scanf(
"%d",&Q);
        vector
<pair<int,pair<int,int> > > VQ,VT;
        VQ.resize(Q);
//
        for(int i=0;i<Q;i++)
        
{
            scanf(
"%d%d",&VQ[i].first,&VQ[i].second.first);
            VQ[i].second.second
=i;
        }

        
for(int i=0;i<R;i++)
            
for(int j=0;j<C;j++)
            
{
                fa[i
*C+j]=i*C+j;
                S[i
*C+j]=1;
                VT.push_back(make_pair(height[i][j],make_pair(i,j)));
            }


        
//按照查询的d排序从大到小查询
        
//然后VT也排序一下,这样就不需多次合并了 用一个指针走下去就行了!
        sort(VQ.begin(),VQ.end());
        sort(VT.begin(),VT.end());

        memset(visit,
0,sizeof(visit));
        vector
<pair<int,pair<int,int> > >::reverse_iterator itQ=VQ.rbegin(),itT=VT.rbegin();
        
for(;itQ!=VQ.rend();itQ++)
        
{
            
int d=itQ->first,A=itQ->second.first,id=itQ->second.second;
            
while(itT!=VT.rend()&&itT->first>d)//
            {    
                
int x=itT->second.first,y=itT->second.second;
                visit[x][y]
=1;                
                mp[
1]++;
                
for(int k=0;k<4;k++)
                
{
                    
int xx=x+dx[k],yy=y+dy[k];
                    
//向高处(visit[,]=1)合并
                    if(chk(xx,yy)&&visit[xx][yy])unit(xx*C+yy,x*C+y);
                }

                itT
++;
            }

            ans[id]
=0;
            
for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++)
            
{
                ans[id]
+=it->second*(1LL<<calc(it->first&A));
            }

        }

        
for(int i=0;i<Q;i++)
            printf(
"%lld\n",ans[i]);
    }

    
return 0;
}