zoukankan      html  css  js  c++  java
  • CF232E Quick Tortoise , Fzoj 3118

    这一题由于数据较多,我们考虑离线处理。

    分治。对于两个点s,t,如果起点在mid这条横线上方,终点在下方,那么它必定会穿过mid这条线。所以只要s可以到mid上一点x,x可以到t,st就是安全的。

    用bitset维护。设(f1[i][j])为上方ij到mid这条线的是否可以的01值,(f2[i][j])为下方ij到mid的01值。将f1[sx][sy]&f2[tx][ty],如果结果存在1,那么就能走到。

    Codeforces版本

    #include <cstdio>
    #include <bitset>
    #include <string>
    #include <algorithm>
    using namespace std;
    const int S=505,N=600003;
    int n,m,Q,fr[S],ed[S];
    char a[S][S];
    bitset<500> f[S][S],g[S][S],h;
    bool res[N];
    struct info
    {
    	int x,y,X,Y,i;
    }w[N];
    void divdo(int l,int r)
    {
    	if (l>r) return;
    	int mid=(l+r)>>1;
    	for (int i=m;i>=1;i--)
    	{
    		if (a[mid][i]=='0')
    		{
    			f[mid][i]=f[mid][i+1];
    			f[mid][i][i]=1;
    		}
    		else f[mid][i].reset();
    	}
    	for (int i=mid-1;i>=l;i--)
    		for (int j=m;j>=1;j--)
    		{
    			f[i][j].reset();
    			if (a[i][j]=='0')
    			{
    				if (a[i+1][j]=='0')
    					f[i][j]|=f[i+1][j];
    				if (a[i][j+1]=='0')
    					f[i][j]|=f[i][j+1];
    			}
    		}
    		
    
    	for (int i=1;i<=m;i++)
    	{
    		if (a[mid][i]=='0')
    		{
    			g[mid][i]=g[mid][i-1];
    			g[mid][i][i]=1;
    		}
    		else g[mid][i].reset();
    	}
    	for (int i=mid+1;i<=r;i++)
    		for (int j=1;j<=m;j++)
    		{
    			g[i][j].reset();
    			if (a[i][j]=='0')
    			{
    				if (a[i-1][j]=='0')
    					g[i][j]|=g[i-1][j];
    				if (a[i][j-1]=='0')
    					g[i][j]|=g[i][j-1];
    			}
    		}
    	for (int i=fr[l];i<=ed[mid];i++)
    	{
    		if (mid<=w[i].X && w[i].X<=r)
    		{
    			h=f[w[i].x][w[i].y]&g[w[i].X][w[i].Y];
    			if (h.any())
    				res[w[i].i]=true;
    		}
    	}
    	divdo(l,mid-1);
    	divdo(mid+1,r);
    }
    void read(int &s)
    {
    	s=0;char c=getchar();
    	while (c<'0' || c>'9') c=getchar();
    	while (c>='0' && c<='9') s=(s<<1)+(s<<3)+(c^48),c=getchar();
    }
    inline bool cmp(const info &a,const info &b)
    {
    	return a.x<b.x;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		scanf("%s",a[i]+1);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			if (a[i][j]=='.')
    				a[i][j]='0';
    			else a[i][j]='1';
    	scanf("%d",&Q);
    	for (int i=1;i<=Q;i++)
    	{
    		read(w[i].x);
    		read(w[i].y);
    		read(w[i].X);
    		read(w[i].Y);
    		w[i].i=i;
    	}
    	sort(w+1,w+1+Q,cmp);
    	int ii=1;
    	for (int i=1;i<=n;i++)
    	{
    		while (ii<=Q && w[ii].x<=i)
    			ii++;
    		ed[i]=ii-1;
    	}
    	ii=Q;
    	for (int i=n;i>=1;i--)
    	{
    		while (ii>=1 && w[ii].x>=i)
    			ii--;
    		fr[i]=ii+1;
    	}
    	divdo(1,n);
    	for (int i=1;i<=Q;i++)
    		if (res[i]) puts("Yes");
    		else puts("No");
    	return 0;
    }
    
    

    Fzoj版本

    #include <cstdio>
    #include <bitset>
    #include <string>
    #include <algorithm>
    using namespace std;
    const int S=505,N=600003;
    int n,m,Q,fr[S],ed[S];
    char a[S][S];
    bitset<500> f[S][S],g[S][S],h;
    bool res[N];
    struct info
    {
    	int x,y,X,Y,i;
    }w[N];
    void divdo(int l,int r)
    {
    	if (l>r) return;
    	int mid=(l+r)>>1;
    	for (int i=m;i>=1;i--)
    	{
    		if (a[mid][i]=='0')
    		{
    			f[mid][i]=f[mid][i+1];
    			f[mid][i][i]=1;
    		}
    		else f[mid][i].reset();
    	}
    	for (int i=mid-1;i>=l;i--)
    		for (int j=m;j>=1;j--)
    		{
    			f[i][j].reset();
    			if (a[i][j]=='0')
    			{
    				if (a[i+1][j]=='0')
    					f[i][j]|=f[i+1][j];
    				if (a[i][j+1]=='0')
    					f[i][j]|=f[i][j+1];
    			}
    		}
    		
    
    	for (int i=1;i<=m;i++)
    	{
    		if (a[mid][i]=='0')
    		{
    			g[mid][i]=g[mid][i-1];
    			g[mid][i][i]=1;
    		}
    		else g[mid][i].reset();
    	}
    	for (int i=mid+1;i<=r;i++)
    		for (int j=1;j<=m;j++)
    		{
    			g[i][j].reset();
    			if (a[i][j]=='0')
    			{
    				if (a[i-1][j]=='0')
    					g[i][j]|=g[i-1][j];
    				if (a[i][j-1]=='0')
    					g[i][j]|=g[i][j-1];
    			}
    		}
    	for (int i=fr[l];i<=ed[mid];i++)
    	{
    		if (l<=w[i].x && w[i].x<=mid && mid<=w[i].X && w[i].X<=r)
    		{
    			h=f[w[i].x][w[i].y]&g[w[i].X][w[i].Y];
    			if (h.any())
    				res[w[i].i]=true;
    		}
    	}
    	divdo(l,mid-1);
    	divdo(mid+1,r);
    }
    void read(int &s)
    {
    	s=0;char c=getchar();
    	while (c<'0' || c>'9') c=getchar();
    	while (c>='0' && c<='9') s=(s<<1)+(s<<3)+(c^48),c=getchar();
    }
    inline bool cmp(const info &a,const info &b)
    {
    	return a.x<b.x;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		scanf("%s",a[i]+1);
    	scanf("%d",&Q);
    	for (int i=1;i<=Q;i++)
    	{
    		read(w[i].x);
    		read(w[i].y);
    		read(w[i].X);
    		read(w[i].Y);
    		w[i].i=i;
    	}
    	sort(w+1,w+1+Q,cmp);
    	int ii=1;
    	for (int i=1;i<=n;i++)
    	{
    		while (ii<=Q && w[ii].x<=i)
    			ii++;
    		ed[i]=ii-1;
    	}
    	ii=Q;
    	for (int i=n;i>=1;i--)
    	{
    		while (ii>=1 && w[ii].x>=i)
    			ii--;
    		fr[i]=ii+1;
    	}
    	divdo(1,n);
    	for (int i=1;i<=Q;i++)
    		if (res[i]) puts("Safe");
    		else puts("Dangerous");
    	return 0;
    }
    
    
  • 相关阅读:
    基础总结篇之一:Activity生命周期
    putExtra方法
    fork函数
    linux中fork()函数详解(原创!!实例讲解) (转载)
    系统调用wait、waitpid和exec函数
    版本控制工具VSS使用介绍
    学习进度条六(第七周)
    阶段冲刺4
    阶段冲刺3
    阶段冲刺2
  • 原文地址:https://www.cnblogs.com/Algebra-hy/p/11121936.html
Copyright © 2011-2022 走看看