/**//* 题意:给出一个地图,一些地方可以走 The ground is constructed in such a way that there is exactly one way to get from one passable cell to another passable cell without visiting any cell twice. 表明是一棵树 然后给出Q个询问,问a到b的最少转的次数 以'#'建一棵树,预处理LCA 然后读入查询,找到LCA 再分情况讨论一下cost[]即可 if LCA(a,b)=a da=0 else 考虑LCA(a,b)向上有没转 有的话da=dist[a]-dist[LCA(a,b)]-1 要-1
R*C<=100000 递归会爆 要用非递归 */ #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<stack> using namespace std;
const int MAXN = 100010;
int dx[4]={1,0,-1,0}; int dy[4]={0,1,0,-1};
char rect[MAXN]; int R,C,root;
int F[MAXN*2],B[MAXN*2]; int pos[MAXN],cost[MAXN],from[MAXN]; int done; vector<pair<int,int> >G[MAXN]; bool vi[MAXN];
/**//* 递归版的 void dfs(int u,int p,int dep,int turn,int k) { from[u]=k; cost[u]=turn; pos[u]=done; F[done]=u; B[done++]=dep; int x=u/C,y=u%C; for(int kk=0;kk<4;kk++) { int xx=x+dx[kk],yy=y+dy[kk],v=xx*C+yy; if(xx<0||xx==R||yy<0||yy==C)continue;//out of bound if(rect[v]!='#'||v==p)continue; dfs(v,u,dep+1,turn+(kk!=k),kk); //下面的要先push后才能push(v) 因为是后序 F[done]=u; B[done]=dep; G[u].push_back(make_pair(done++,kk));// } } */
struct State { bool flag; int u,dep,turn,k; State(bool flag,int u,int dep,int turn,int k):flag(flag),u(u),dep(dep),turn(turn),k(k){} };
void dfs(int u)//u p dep turn k { stack<State>S; S.push(State(false,u,0,0,0)); while(!S.empty()) { State top=S.top(); S.pop(); if(top.flag) { F[done]=top.u; B[done]=top.dep; G[top.u].push_back(make_pair(done++,top.k));// } else { vi[top.u]=1; from[top.u]=top.k; cost[top.u]=top.turn; pos[top.u]=done; F[done]=top.u; B[done++]=top.dep; int x=top.u/C,y=top.u%C; for(int kk=0;kk<4;kk++) { int xx=x+dx[kk],yy=y+dy[kk],v=xx*C+yy; if(xx<0||xx==R||yy<0||yy==C)continue;//out of bound if(rect[v]!='#'||vi[v])continue; S.push(State(true,top.u,top.dep,top.turn,kk));// S.push(State(false,v,top.dep+1,top.turn+(kk!=from[top.u]),kk)); } } } }
//rmq int rmq[2*MAXN][18];//注意要乘以2 void initRMQ() { for(int i=0;i<done;i++)rmq[i][0]=i; for(int j=1;(1<<j)<=done;j++) for(int i=0;i+(1<<j)-1<done;i++) if(B[rmq[i][j-1]]<B[rmq[i+(1<<(j-1))][j-1]])rmq[i][j]=rmq[i][j-1]; else rmq[i][j]=rmq[i+(1<<(j-1))][j-1]; } inline int RMQ(int a,int b) { int k=0; while(1<<(k+1)<(b-a+1))k++; if(B[rmq[a][k]]<B[rmq[b-(1<<k)+1][k]])return F[rmq[a][k]]; return F[rmq[b-(1<<k)+1][k]]; } inline int LCA(int a,int b) { if(pos[a]<pos[b])return RMQ(pos[a],pos[b]); return RMQ(pos[b],pos[a]); }
int main() { scanf("%d%d",&R,&C); for(int i=0;i<R;i++) scanf("%s",&rect[i*C]); for(int i=0;;i++) if(rect[i]=='#'){root=i;break;}
done=0; dfs(root); initRMQ(); int Q; scanf("%d",&Q); while(Q--) { int a,b,c,x1,x2,y1,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); a=(--x1)*C+(--y1); b=(--x2)*C+(--y2); c=LCA(a,b); int da,db,ka,kb;//da db为到LCA的turn的次数 if(c==a)da=0; else { da=cost[a]-cost[c]; int i=0; while(pos[a]>G[c][i].first)i++; ka=G[c][i].second; if(from[c]!=ka)da--;//c向上要转的话就-1 } if(c==b)db=0; else { db=cost[b]-cost[c]; int i=0; while(pos[b]>G[c][i].first)i++; kb=G[c][i].second; if(from[c]!=kb)db--; } printf("%d\n",da+db+ ((c!=a&&c!=b)&&(ka&1)!=(kb&1)) ); } return 0; }
|