zoukankan      html  css  js  c++  java
  • CF232E Quick Tortoise

    题目传送门

    分析:
    暴力DP无法通过,考虑按横坐标进行分治
    假设目前分治区间中点为(mid),沿这一列将矩形划分成两份,如果一次询问两端分别在两边,那么其路线一定经过(mid)这一列上的某一点
    (f[x][y][k]=0/1)表示((x,y))能否走到((k,mid))
    最后答案只需要判断是否存在一个(k)使得(f[x1][y1][k]&f[x2][y2][k]=1)
    暴力转移是(O(nm^2logn))的,会超时
    发现(f)值只有(0/1),尝试用bitset优化这个转移
    复杂度变为(O(frac{nm^2logn}{32})),CF少爷机可以通过

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<queue>
    #include<bitset>
    #include<map>
    #include<set>
    
    #define maxn 505
    #define maxm 1000005
    #define INF (1ll<<60)
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,m,Q;
    bitset<maxn>f[maxn][maxn],g[maxn][maxn];
    char s[maxn][maxn];
    bool ans[maxm];
    struct node{
    	int x1,y1,x2,y2,id;
    }q[maxm],tmp1[maxm],tmp2[maxm];
    
    inline void solve(int l,int r,int ql,int qr)
    {
    	if(l>r||ql>qr)return;
    	int cnt1=0,cnt2=0,mid=(l+r)>>1;
    	for(int i=1;i<=m;i++)f[mid][i]=g[mid][i]=0;
    	for(int i=m;i;i--)if(s[mid][i]=='.')f[mid][i][i]=1,f[mid][i]|=f[mid][i+1];
    	for(int i=1;i<=m;i++)if(s[mid][i]=='.')g[mid][i][i]=1,g[mid][i]|=g[mid][i-1];
    	for(int i=mid-1;i>=l;i--)for(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(int i=mid+1;i<=r;i++)for(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(int i=ql;i<=qr;i++)
    	{
    		if(q[i].x2<mid){tmp1[++cnt1]=q[i];continue;}
    		if(q[i].x1>mid){tmp2[++cnt2]=q[i];continue;}
    		ans[q[i].id]=(f[q[i].x1][q[i].y1]&g[q[i].x2][q[i].y2]).any();
    	}
    	for(int i=1;i<=cnt1;i++)q[ql+i-1]=tmp1[i];
    	for(int i=1;i<=cnt2;i++)q[qr-i+1]=tmp2[i];
    	solve(l,mid-1,ql,ql+cnt1-1);
    	solve(mid+1,r,qr-cnt2+1,qr);
    }
    
    int main()
    {
    	n=getint(),m=getint();
    	for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
    	Q=getint();
    	for(int i=1;i<=Q;i++)q[i].x1=getint(),q[i].y1=getint(),q[i].x2=getint(),q[i].y2=getint(),q[i].id=i;
    	solve(1,n,1,Q);
    	for(int i=1;i<=Q;i++)puts(ans[i]?"Yes":"No");
    }
    

  • 相关阅读:
    解决WampServer窗口界面乱码问题
    PHP 中空字符串介绍0、null、empty和false之间的关系
    位(bit)、字节(byte)、字
    SQL GROUP BY 和 ORDER BY 区别
    爬虫安装相关软件
    nginx自动切割日志脚本
    tengine日志切割-配置分钟级别日志自动切割
    flutter进行自动编译操作步骤
    03-字符编码-读写模式-课堂笔记
    04-函数-课堂笔记
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13273494.html
Copyright © 2011-2022 走看看