• [CF232E]Quick Tortoise


    题目大意:
      给你一个$n imes m(n,mleq 500)$的格子,有一些是障碍物。从一个格子出发只能向下或向右走,有$q$组询问,每次询问从一个点是否能够到达另一个点。

    思路:
      分治。
      两点间的路径必然会经过两点间的某条竖线。
      我们可以二分一个区间内中间一条线$mid$,
      对于$mid$左边的点,求出到$mid$为止往右下走能够到达的点,
      对于$mid$右边的点,求出从$mid$开始往右下走会被哪些点到达。
      这可以用bitdet来存。
      对于不经过这条竖线的路径,可以往下递归查找。
      回答询问时,只需要找到一开始选的两点之间的竖线,然后判一下一个点能到达的点和另一个点被到达的点有没有交集即可。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<bitset>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 inline bool getblock() {
    12     register char ch=getchar();
    13     while(ch!='.'&&ch!='#') ch=getchar();
    14     return ch=='.';
    15 }
    16 const int N=502,logN=9;
    17 int n,m;
    18 bool map[N][N];
    19 std::bitset<N> f[N][N][logN],g[N][N][logN];
    20 void solve(const int &l,const int &r,const int &k) {
    21     if(l>r) return;
    22     const int mid=(l+r)/2;
    23     solve(l,mid-1,k+1);
    24     solve(mid+1,r,k+1);
    25     for(register int i=n;i;i--) {
    26         if(map[i][mid]) {
    27             f[i][mid][k][i]=true;
    28             f[i][mid][k]|=f[i+1][mid][k];
    29         }
    30         for(register int j=mid-1;j>=l;j--) {
    31             if(map[i][j]) {
    32                 f[i][j][k]|=f[i+1][j][k]|f[i][j+1][k];
    33             }
    34         }
    35     }
    36     for(register int i=1;i<=n;i++) {
    37         if(map[i][mid]) {
    38             g[i][mid][k][i]=true;
    39             g[i][mid][k]|=g[i-1][mid][k];
    40         }
    41         for(register int j=mid+1;j<=r;j++) {
    42             if(map[i][j]) {
    43                 g[i][j][k]|=g[i-1][j][k]|g[i][j-1][k];
    44             }
    45         }
    46     }
    47 }
    48 int calc(const int &l,const int &r,const int &k,const int &y1,const int &y2) {
    49     const int mid=(l+r)/2;
    50     if(y2<mid) return calc(l,mid-1,k+1,y1,y2);
    51     if(y1>mid) return calc(mid+1,r,k+1,y1,y2);
    52     return k;
    53 }
    54 inline bool check(const int &x1,const int &y1,const int &x2,const int &y2) {
    55     if(x1>x2||y1>y2) return false;
    56     const int k=calc(1,m,0,y1,y2);
    57     return (f[x1][y1][k]&g[x2][y2][k]).count();
    58 }
    59 int main() {
    60     n=getint(),m=getint();
    61     for(register int i=1;i<=n;i++) {
    62         for(register int j=1;j<=m;j++) {
    63             map[i][j]=getblock();
    64         }
    65     }
    66     solve(1,m,0);
    67     for(register int q=getint();q;q--) {
    68         const int x1=getint(),y1=getint(),x2=getint(),y2=getint();
    69         puts(check(x1,y1,x2,y2)?"Yes":"No");
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    ASP.NET中JSON的序列化和反序列化
    Android:数据存储之SQLite
    转Android:简单联网获取网页代码
    Android:@id和@+id
    linux .run文件安装
    Mysql的Root密码忘记,查看或修改的解决方法(图文介绍)
    网页页面尺寸
    openstack
    br0
    virsh
  • 原文地址:https://www.cnblogs.com/skylee03/p/8252304.html
Copyright © 2020-2023  润新知