文章目录
R e s u l t Result Result
H y p e r l i n k Hyperlink Hyperlink
https://www.luogu.com.cn/problem/CF232E
D e s c r i p t i o n Description Description
给定一个 n × m n\times m n×m的网格,有些格子不能走,每次只能向右或向下走, Q Q Q次询问,每次询问一个点能否到另一个点
数据范围: n , m ≤ 500 , Q ≤ 6 × 1 0 5 n,m\leq 500,Q\leq 6\times 10^5 n,m≤500,Q≤6×105
S o l u t i o n Solution Solution
将询问离线后分治,对于一组查询的 x x x位于 [ L , R ] [L,R] [L,R]的询问,若能到达,其必然存在一条路径使得出发点可以到达 ( m i d , i ) (mid,i) (mid,i),然后从 ( m i d , i ) (mid,i) (mid,i)可以到达终点
至此,我们可以用 f i , j , k f_{i,j,k} fi,j,k表示从 ( i , j ) (i,j) (i,j)出发能否到达 ( m i d , k ) (mid,k) (mid,k),用 g i , j , k g_{i,j,k} gi,j,k表示从 ( m i d , k ) (mid,k) (mid,k)出发能否到达 ( i , j ) (i,j) (i,j),对于后者,我们直接倒序转移即可
通过 f [ x ] [ y ] & g [ q x ] [ q y ] f[x][y]\& g[qx][qy] f[x][y]&g[qx][qy]即可得到是否有解
使用 b i t s e t bitset bitset优化后即可通过本题
时间复杂度: O ( n 2 m log n ω + Q log n ) O(\frac{n^2m\log n}\omega+Q\log n) O(ωn2mlogn+Qlogn)
C o d e Code Code
//#pragma GCC optimize(2)
//%:pragma GCC optimize(3)
//%:pragma GCC optimize("Ofast")
//%:pragma GCC optimize("inline")971955756
#include<cctype>
#include<cstdio>
#include<bitset>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;int n,m,Q,p,ans[600010];
char s[510][510];
struct node{int x,y,qx,qy,id;}q[600010],t[600010];
inline LL read()
{
char c;LL d=1,f=0;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
bitset<501>f[501][501],g[501][501];
inline void solve(int l,int r,int ql,int qr)
{
if(l>r||ql>qr) return;
int tl=ql-1,tr=qr+1,mid=l+r>>1;
for(register int i=1;i<=m;i++) f[mid][i]=g[mid][i]=0;
for(register int i=m;i;i--) if(s[mid][i]=='.') f[mid][i][i]=1,f[mid][i]|=f[mid][i+1];
for(register int i=1;i<=m;i++) if(s[mid][i]=='.') g[mid][i][i]=1,g[mid][i]|=g[mid][i-1];
for(register int i=mid-1;i>=l;i--) for(register int j=m;j;j--) if(s[i][j]=='.') f[i][j]=f[i+1][j]|f[i][j+1];else f[i][j]=0;
for(register int i=mid+1;i<=r;i++) for(register int j=1;j<=m;j++) if(s[i][j]=='.') g[i][j]=g[i-1][j]|g[i][j-1];else g[i][j]=0;
for(register int i=ql;i<=qr;i++)
{
if(q[i].qx<mid) {t[++tl]=q[i];continue;}
if(q[i].x>mid) {t[--tr]=q[i];continue;}
ans[q[i].id]=(f[q[i].x][q[i].y]&g[q[i].qx][q[i].qy]).any();
}
for(register int i=ql;i<=tl;i++) q[i]=t[i];
for(register int i=tr;i<=qr;i++) q[i]=t[i];
solve(l,mid,ql,tl);solve(mid+1,r,tr,qr);
return;
}
signed main()
{
// freopen("grid.in","r",stdin);
// freopen("grid.out","w",stdout);
n=read();m=read();
for(register int i=1;i<=n;i++) scanf("%s",s[i]+1);
Q=read();
for(register int i=1;i<=Q;i++)
{
q[i].x=read();q[i].y=read();
q[i].qx=read();q[i].qy=read();
q[i].id=i;
}
solve(1,n,1,Q);
for(register int i=1;i<=Q;i++) puts(ans[i]?"Yes":"No");
}