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;
}

原文地址:https://www.cnblogs.com/Algebra-hy/p/11121936.html

时间: 2024-11-13 06:53:07

CF232E Quick Tortoise , Fzoj 3118的相关文章

cf232E. Quick Tortoise(分治 bitset dp)

题意 题目链接 Sol 感觉这个思路还是不错的 #include<bits/stdc++.h> using namespace std; const int MAXN = 501, SS = 5e6 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '

CodeForces 232E.Quick Tortoise

John Doe has a field, which is a rectangular table of size n × m. We assume that the field rows are numbered from 1 to n from top to bottom, and the field columns are numbered from 1 to m from left to right. Then the cell of the field at the intersec

quick 受伤,当时错误,是因为命令行没有拉全

local scheduler = require(cc.PACKAGE_NAME .. ".scheduler") local MainScene = class("MainScene", function() return display.newScene("MainScene") end) local interval=0 function MainScene:ctor() self.box=display.newSprite("

Quick cocos2dx-Lua(V3.3R1)学习笔记(十)-----搭建安卓打包环境,用官方示例anysdk生成apk运行

话说我这一篇就写搭建打包安卓环境,是不是有点过早了(其实我主要是怕以后重装系统,忘了怎么搭建了),但是迟早要面对的痛苦,一直延后也不是办法,对吧. 在官方文档中,对于打包安卓apk,已经很清楚了,我写这个这篇,只不过加点图片,介绍的更加详细. 搭建打包安卓环境,需要很多安装很多东东,我直接将我用的全部打包上传到网盘了,需要的朋友,去网盘下载就行了 整合包网盘下载地址:http://pan.baidu.com/s/1hquz7fe     密码:r2nq 一,搭建安卓环境 我在我G盘根目录下新建一

记录quick cocos2d-x3.2升级至cocos2d-x3.8

目前为止,quickcocos2d-x没有3.8版本,想用3.8又想用quick,所以只能自己升级了,自己先记录下,防止忘记. cocos2d-x3.8里面有quick framework,而simulator可以暂时代替quick的player,所以就暂时先用simulator. 用3.8新建一个lua工程,然后到目录frameworks\runtime-src\proj.win32用vs打开工程编一个simulator,编之前先更改 SimulatorWin.cpp文件的一个参数 #if (

Android Studio中常用设置与快捷键(私人珍藏,Eclipse转AS必看)

常用设置: 1.Tab不用4个空格 Code Style->Java->Tabs and Indents->Use tab character Code Style->General->Use tab character               (例如:版本控制Diff界面按下Tab) 2.可视化Tab和空格 Settings->IDE Settings->Editor->Appearance->Show whitespaces 3.显示代码行数

Qt Quick 之 QML 与 C++ 混合编程详解

Qt Quick 技术的引入,使得你能够快速构建 UI ,具有动画.各种绚丽效果的 UI 都不在话下.但它不是万能的,也有很多局限性,原来 Qt 的一些技术,比如低阶的网络编程如 QTcpSocket ,多线程,又如 XML 文档处理类库 QXmlStreamReader / QXmlStreamWriter 等等,在 QML 中要么不可用,要么用起来不方便,所以呢,很多时候我们是会基于这样的原则来混合使用 QML 和 C++: QML 构建界面, C++ 实现非界面的业务逻辑和复杂运算. 请给

一组图表告诉你,AWS为什么刚刚启动了K8S 容器项目

K8S技术社区正式上线啦!快快关注找到志同道合的小伙伴! 2017年3月,AWS与K8S(Kubernetes)创业公司Heptio联合启动了K8S Quick Start,Heptio将帮助AWS解决方案架构团队设计K8S参考架构. 此前,K8S已被应用于Azure.DC/OS以及几乎所有知名的云平台,而Amazon Web Services(AWS)是唯一的例外.Amazon在2016年的re:Invent大会上发布AWS Blox的时候还曾阻击K8S.Blox是一个开源项目,支持用户在Am

eclipse 字体、主题、工具条、Quick Access配置

Tip_self:本次去掉了一个工具栏 Window->Customize- Perspactive中的Tool Bar Visibility--Editor Presentation(去掉选重)--OK ------ 一.eclipse字体调整: windows7系统下eclipse的默认字体里面有的没有Courier New这种字体,采用eclipse默认字体Consolas程序代码字母间距明显增大,习惯XP 系统下的eclipse用户会感觉很不习惯,字体Courier New会让代码更整齐