标签:分治 Tortoise int 中转 CF232E mid read while Quick
一、题目
二、解法
考虑找中转点,也就是起点能到这个中转点并且中转点能到终点。
有一个重要的转化:要么不存在中转点,要么起点到终点的每一行都存在至少一个中转点。
那么以行为中心处理每个点到这一行的状态即可,暴力 \(\tt bitset\) 需要 \(O(\frac{n^4}{w})\)
然后我们主动使用分治,考虑中点分治,每次处理过中点的询问。可以处理出 \(b(i,j,k)\) 表示点 \((i,j)\) 是否能到达 \((mid,k)\),可以用 \(\tt bitset\) 优化,先分治得到信息之后可以在线询问,那么时间复杂度 \(O(\frac{n^3\log n}{w}+q\log n)\)
三、总结
我觉得本题重要的是那一步转化,它缩小的答案范围,从而符合了中点分治的模型。
#include <cstdio>
#include <bitset>
using namespace std;
const int M = 505;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,q,D[4*M],num[M];char s[M][M];bitset<M> b[11][M][M];
void cdq(int x,int l,int r,int d)
{
int mid=(l+r)>>1;D[x]=d;
for(int i=1;i<=m;i++)
if(s[mid][i]=='.')
{
b[d][mid][i][i]=1;
b[d][mid][i]|=b[d][mid][i-1];
}
for(int i=mid+1;i<=r;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='.')
b[d][i][j]|=b[d][i-1][j]|b[d][i][j-1];
for(int i=m;i>=1;i--)
{
b[d][mid][i].reset();
if(s[mid][i]=='.')
{
b[d][mid][i][i]=1;
b[d][mid][i]|=b[d][mid][i+1];
}
}
for(int i=mid-1;i>=l;i--)
for(int j=m;j>=1;j--)
if(s[i][j]=='.')
b[d][i][j]|=b[d][i+1][j]|b[d][i][j+1];
if(l==r)
{
num[l]=x;
return ;
}
cdq(x<<1,l,mid,d+1);cdq(x<<1|1,mid+1,r,d+1);
}
int get(int a,int B,int c,int d)
{
int x=num[a],y=num[c];
while(D[x]>D[y]) x>>=1;
while(D[x]<D[y]) y>>=1;
while(x!=y) x>>=1,y>>=1;
return (b[D[x]][a][B]&b[D[x]][c][d]).count();
}
signed main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
cdq(1,1,n,0);
q=read();
while(q--)
{
int a=read(),b=read(),c=read(),d=read();
if(get(a,b,c,d)) puts("Yes");
else puts("No");
}
}
标签:分治,Tortoise,int,中转,CF232E,mid,read,while,Quick 来源: https://www.cnblogs.com/C202044zxy/p/15106916.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。