在平面上有一个大小为 n 行 m 列的 01 矩阵。每次读入两个点的坐标,假设分别是 (x1,y1),(x2,y2)。希望你能回答能否从 (x1,y1) 仅向右向下走到达 (x2,y2)。
矩阵中所有标记着 1 的点无法通行,且并且保证询问的点上是 0。
数据范围:n,m<=500,q<=1000000。
题解
如果对于单独的一个询问,我们当然可以直接暴搜出是否可达,但复杂度高达 O(nmq),考虑能否通过一次预处理解决多次询问。
显然,如果 (x1,y1) 能够仅向右向下走到达第 i 行的某个点,同时 (x2,y2) 能够仅向左向上走到达这个点,那么 (x1,y1) 与 (x2,y2) 就是互相可达的。
于是,我们可以预处理出每个点到第 i 行的可达情况,就可以求出所有跨过第 i 行的询问的答案了,用 bitset 可以将预处理优化到 O(wn3),单次询问可做到 O(wn)。
但是,这仍然不够,还有未跨过第 i 行的询问,这时我们就可以使用分治,设询问的行所在的区间为 [l,r],我们预处理出第 mid 行的可达情况,对于未跨过 mid 的询问分治处理即可。
时间复杂度为 O(wn3logn+wqn)。
小结
在上题中,我们其实将多组询问分成了 3 部分:
- x1≤mid≤x2 的询问。
- x1≤x2<mid 的询问。
- mid<x1≤x2 的询问。
对于第一类询问,我们可以借助预处理快速得到答案,对于第二类和第三类询问,我们递归地处理。实际上,这就是 CDQ 分治的思想,我们是把询问 (x1,y1),(x2,y2) 抽象成了一个点对 (x1,x2),利用 CDQ 分治对点对的划分解决问题。
在做题过程中,如果题目中的多组询问也可以按照上述的规则划分,并能快速处理第一类询问的话,我们就可以考虑用 CDQ 分治来解决。
集训总结
这一个月以来,我们一起经历挂分了 25 场模拟赛,一起切做过 20+ 道蓝题,30+ 道紫题,3 道黑题,我不但结识了各路大佬,也从一个线段树板子都会写挂的蒟蒻磨砺成为了一个能在难题前稳住心态的选手,学到了各种 OI 知识和奇异淫巧。
最后,祝大家 NOIP2023 rp++!以及 NOI2024 rp++(?)