从$(0,0)$开始BFS$2\times10^6$步,那么迷宫的形状有三种:
1.走不完$2\times10^6$步,直接判定即可。
2.可以走到$(n,0)$以及$(0,m)$,那么直接把询问点平移到一开始的小迷宫里即可。
3.可以沿着$(dx,dy)$这个向量达到某些左上角,那么先三分沿向量走的步数,把询问点平移到最近距离之后再判定。
#include<cstdio>
typedef long long ll;
const int N=105,M=2000010,U=(1<<24)-1;
int n,m,_,flag,dx,dy,i,j,x,y,h=1,t,q[M][2];char a[N][N];
struct E{int x,y;E*nxt;}*g[U+1],pool[M],*cur=pool,*p;
inline void read(int&a){
char c;bool f=0;a=0;
while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
if(c!='-')a=c-'0';else f=1;
while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
if(f)a=-a;
}
inline void ins(int x,int y){
int u=((x<<9)^y)&U;
p=cur++;p->x=x;p->y=y;p->nxt=g[u];g[u]=p;
}
inline bool ask(int x,int y){
for(p=g[((x<<9)^y)&U];p;p=p->nxt)if(p->x==x&&p->y==y)return 1;
return 0;
}
inline int pos(int x,int n){return (x%n+n)%n;}
inline void ext(int x,int y){
if(t==M-1)return;
if(!a[pos(x,n)][pos(y,m)])return;
if(ask(x,y))return;
q[++t][0]=x;q[t][1]=y;ins(x,y);
}
inline ll abs(ll x){return x>0?x:-x;}
inline ll dis(int x,int y,ll k){return abs(k*dx+x)+abs(k*dy+y);}
inline bool query(int x,int y){
if(t<M-1)return ask(x,y);
if(flag)return ask(pos(x,n),pos(y,m));
ll l=-1000000000,r=1000000000;
while(l+5<r){
ll len=(r-l)/3,m1=l+len,m2=r-len;
if(dis(x,y,m1)<dis(x,y,m2))r=m2;else l=m1;
}
for(;l<=r;l++)if(dis(x,y,l)<=M)if(ask(l*dx+x,l*dy+y))return 1;
return 0;
}
int main(){
read(n),read(m);
for(i=0;i<n;i++)for(scanf("%s",a[i]),j=0;j<m;j++)a[i][j]=a[i][j]=='.';
ext(0,0);
while(h<=t){
x=q[h][0];y=q[h++][1];
ext(x-1,y);
ext(x+1,y);
ext(x,y-1);
ext(x,y+1);
}
if(t==M-1){
if(ask(n,0)&&ask(0,m))flag=1;else for(i=2;i<=t;i++){
x=q[i][0],y=q[i][1];
if(x%n||y%m)continue;
dx=x,dy=y;
break;
}
}
read(_);
while(_--)read(x),read(y),puts(query(x,y)?"yes":"no");
return 0;
}