只能说没想到


题面

给出一个 \(n\times m\) 的网格图,每个格子要么是空地要么是障碍。

给出 \(q\) 个询问,每次给出 \((sx, sy),(ex,ey)\),问从 \((sx,sy)\) 出发,只能向下或向右走,能否到达 \((ex,ey)\)。

数据规模:\(n,m\le500\),\(q\le6\times10^5\)。


解析

只能向右或向下走就保证了转移无环,由此联想到另一道题(忘了具体哪道题了):用线段树维护从 \((l,i)\) 到 \((r,j)\) 的路径信息。该题主要利用了两条路径比较容易合并的性质。

这道题不涉及修改,不需要线段树,可以直接猫树分治

将询问离线,每次处理横坐标跨过区间中点的询问。对区间 \([l,r]\) 只需要预处理 \((p,i)\to(mid,k)\)(\(p\in[l,mid]\))的连通性和 \((mid,k)\to(q,j)\)(\(q\in[mid,r]\))的连通性即可。

询问只需要判断是否存在 \(k\) 使得路径 \((sx,sy)\to(mid,k)\to(ex,ey)\) 合法。

可以用 bitset 优化 —— 储存 \((p,i)\) 向右下走能到达 \(x=mid\) 的哪些点,以及 \((q,j)\) 向左上走能到达 \(x=mid\) 的哪些点。查询可以一次 bitset 求交集。

复杂度 \(\mathcal{O}(\frac{n^3\log n+nq}{w})\)。


源代码

/* Lucky_Glass */
#include <bitset>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <algorithm> #define CON(typ) const typ & const int N = 505, M = 6e5 + 10; int rin(int &r) {
int c = getchar(); r = 0;
while (c < '0' || '9' < c) c = getchar();
while ('0' <= c && c <= '9') r = r * 10 + (c ^ '0'), c = getchar();
return r;
} int n, m, qry_cnt;
char maz[N][N];
int qry[M][4], qry_id[M], tmp_id[M];
bool ans[M];
std::bitset<N> dp[N][N], dp_rev[N][N]; void solve(CON(int) xl, CON(int) xr, CON(int) ql, CON(int) qr) {
if (ql > qr) return;
assert(xl <= xr);
int mi = (xl + xr) >> 1; for (int j = m; j; --j)
if (maz[mi][j] == '.') dp[mi][j] = dp[mi][j + 1], dp[mi][j].set(j, 1);
else dp[mi][j] = 0;
for (int i = mi - 1; i >= xl; --i)
for (int j = m; j; --j)
if (maz[i][j] == '.') dp[i][j] = dp[i + 1][j] | dp[i][j + 1];
else dp[i][j] = 0; for (int j = 1; j <= m; ++j)
if (maz[mi][j] == '.') {
dp_rev[mi][j] = dp_rev[mi][j - 1], dp_rev[mi][j].set(j, 1);
} else {
dp_rev[mi][j] = 0;
}
for (int i = mi + 1; i <= xr; ++i)
for (int j = 1; j <= m; ++j)
if (maz[i][j] == '.') dp_rev[i][j] = dp_rev[i - 1][j] | dp_rev[i][j - 1];
else dp_rev[i][j] = 0; int qll = ql - 1, qrr = qr + 1;
for (int i = ql; i <= qr; ++i)
if (qry[qry_id[i]][0] <= mi && mi <= qry[qry_id[i]][2]) {
int *now = qry[qry_id[i]];
ans[qry_id[i]] = (dp[now[0]][now[1]] & dp_rev[now[2]][now[3]]) != 0;
} else if (qry[qry_id[i]][0] > mi) {
tmp_id[--qrr] = qry_id[i];
} else {
tmp_id[++qll] = qry_id[i];
}
for (int i = ql; i <= qll; ++i) qry_id[i] = tmp_id[i];
for (int i = qrr; i <= qr; ++i) qry_id[i] = tmp_id[i]; solve(xl, mi - 1, ql, qll);
solve(mi + 1, xr, qrr, qr);
}
int main() {
rin(n), rin(m);
for (int i = 1; i <= n; ++i) scanf("%s", maz[i] + 1);
rin(qry_cnt);
for (int i = 1; i <= qry_cnt; ++i) {
rin(qry[i][0]), rin(qry[i][1]), rin(qry[i][2]), rin(qry[i][3]);
qry_id[i] = i;
} solve(1, n, 1, qry_cnt); for (int i = 1; i <= qry_cnt; ++i)
printf("%s\n", ans[i] ? "Yes" : "No");
return 0;
}

THE END

Thanks for reading!

历过沧海的变迁
再难为江河的涡旋
我寻找着 沉默的桑田 坎坷万千
眺望过巫山之巅
再不是浮云的翩跹
我寻找着 属于我的那片云烟
在下个时刻出现

——《巫山云》By Snapmod / 诗岸

Link 巫山云 - 网易云

「SOL」Quick Tortoise (Codeforces)的更多相关文章

  1. Solution -「CF 232E」Quick Tortoise

    \(\mathcal{Description}\)   Link.   在一张 \(n\times m\) 的网格图中有空格 . 和障碍格 #,\(q\) 次询问,每次查询从 \((x_1,y_1)\ ...

  2. 一本通1648【例 1】「NOIP2011」计算系数

    1648: [例 1]「NOIP2011」计算系数 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 给定一个多项式 (ax+by)k ,请求出多项式展开后 x ...

  3. 「SCOI2016」背单词

    「SCOI2016」背单词 Lweb 面对如山的英语单词,陷入了深深的沉思,「我怎么样才能快点学完,然后去玩三国杀呢?」.这时候睿智的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,然后 ...

  4. loj2009. 「SCOI2015」小凸玩密室

    「SCOI2015」小凸玩密室 小凸和小方相约玩密室逃脱,这个密室是一棵有 $ n $ 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 $ A_i $,每条边也有个 ...

  5. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  6. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  7. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  8. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  9. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  10. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

随机推荐

  1. Vue+Element-Ui设置收货地址,省市区三级联动,详细地址信息调用腾讯地图关键词输入提示api

    省市区三级联动的数据 我这里找了一个json格式的数据,直接放在前端项目的文件夹下,这里粘贴出来 pca.json文件内容 { "北京市": { "市辖区": ...

  2. Task记录1.CancellationToken 取消Task任务的操作

    //1.创建取消令牌数据 CancellationTokenSource tokenSource = new CancellationTokenSource(); //2.创建取消令牌 Cancell ...

  3. 一文看懂 Python 中的函数参数

    函数定义中的参数也就是形式参数,规定了在调用函数时如何传递实际参数以及这些参数有无默认值. 实参传递方式 def f(a): print(a) 实参传递方式有两种,位置和关键字.对于上面定义的函数 f ...

  4. day09-2-验证以及国际化

    验证以及国际化 1.概述 (1)概述 对于输入的数据(比如表单数据),进行必要的验证,并给出相应的提示信息 对于验证表单数据,SpringMVC 提供了很多使用的注解,这些注解由 JSR 303验证框 ...

  5. STM32F4寄存器初始化:编码器

    RCC->APB1ENR|=1<<0; //TIM2时钟使能 RCC->APB1ENR|=1<<1; //TIM3时钟使能 RCC->APB1ENR|=1&l ...

  6. 基于ROS的串口底层写法

    serial_device.cpp #include "serial_device.h" namespace roborts_sdk { SerialDevice::SerialD ...

  7. Excel操作技巧

    命令 获取行号ROW(D2).COLOUM(D2) 快捷键 alt+=求和:alt+f1生成柱形图:alt+回车强制换行:alt+178输入平方:alt+179输入立方: shitf+大十字光标 换位 ...

  8. KingbaseES R6集群误删除备节点的集群目录恢复方式

    一.场景 一主一备环境 主节点:192.168.17.9 备节点:192.168.17.10 故障:备节点安装目录/home/kingbase/cluster备删除 二.恢复方式 1.备节点集群目录备 ...

  9. pycharm取消代码长度的竖线

  10. Android 之Map容器替换 SparseArray,ArrayMap,ArraySet

    高效程序有两个重要指标:速度,内存,移动app中内存比重要多一些,为此在速度相差不是很大的时候,优先考虑内存,container是一个重要部分,对此google对一些原java容器设计新的容器进行替换 ...