1 条题解

  • 0
    @ 2026-5-19 20:43:36

    题目理解

    我们有一个矩形区域,左下角是 (0,0)(0,0),右上角是 (x,y)(x,y),需要从起点 (0,0)(0,0) 走到终点 (x,y)(x,y)

    矩形内有一些 水平激光:第 ii 条水平激光在 y=aiy = a_i 上,从 (0,ai)(0, a_i)(x,ai)(x, a_i)
    还有一些 垂直激光:第 ii 条垂直激光在 x=bix = b_i 上,从 (bi,0)(b_i, 0)(bi,y)(b_i, y)

    我们从起点到终点的路径必须是连续的曲线,可以任意方向走,但每穿过一次激光线就计一次穿越
    如果经过某条水平激光和某条垂直激光的交点,那么因为同时穿过它们,算 两次 穿越。

    题目要求 最少的穿越次数


    关键观察

    1. 起点与终点
      起点 (0,0)(0,0) 和终点 (x,y)(x,y) 都在矩形的两个对角,且它们都不在激光上(因为水平激光的 0<ai<y0 < a_i < y,垂直激光的 0<bi<x0 < b_i < x)。

    2. 激光的阻挡作用
      如果我们想从 (0,0)(0,0)(x,y)(x,y),必须“跨过”这些激光。
      在一个方向(例如水平方向)上,如果我们沿着一条 yy 常数的线水平穿过,就会垂直跨过一条垂直激光;
      沿着一条 xx 常数的线垂直穿过,就会水平跨过一条水平激光。

    3. 交点计数
      如果同时经过一个交点,算两次。那么要最小化穿越次数,我们应该尽量 避免同时经过交点,除非这样可以节省总的穿越数吗?
      仔细想:比如从 (0,0)(0,0)(x,y)(x,y),经过一个交点意味着你同时跨过了一条水平激光和一条垂直激光,这在路径上是不可避免的吗?

    4. 简化问题
      观察一个简单情况:假设没有激光,穿越次数 = 0。
      如果有若干激光,我们必须穿过去。
      实际上,起点到终点必然会在 xx 方向上跨越所有 bib_i 的垂线?不一定,因为我们可以走一条弯曲的路径绕过某些激光?
      等一下,垂直激光是从 (bi,0)(b_i, 0)(bi,y)(b_i, y),是贯穿整个 yy 轴的,所以无法绕过——你必须从垂直激光的左边走到右边,而垂直激光挡住了整个 yy 范围,所以你必须穿过它一次(即在 xx 方向跨过 bib_i)。

    同样,水平激光贯穿整个 xx 轴,所以你必须从水平激光的下方走到上方,因此你必须穿过它一次。

    所以:

    • 每条垂直激光必须被穿过至少一次。
    • 每条水平激光必须被穿过至少一次。

    那岂不是答案 = n+mn + m
    但是示例 1 中 n=m=1n=m=1,答案却是 22,刚好 n+mn+m 就是 22,似乎没问题。
    但示例 2 中,n=2,m=1n=2, m=1,答案却是 33,也是 n+m=3n+m=3

    这让人怀疑是否总是 n+mn+m
    看另一个情况:如果水平激光和垂直激光有交点,你可以利用交点同时穿过两条激光,从而节省一次穿越吗?
    题目明确说了,在交点算两次,所以不会节省。而且你必须分别穿过水平激光的线和垂直激光的线,无法绕过。

    所以结论:每条激光至少被穿过一次,且无法一次穿过两条(因为交点算两次),所以最少就是 n+mn + m

    但等等——题目给的示例 2,n=2,m=1n=2,m=1n+m=3n+m=3 匹配,但 n=2,m=1,x=100000,y=100000n=2,m=1,x=100000,y=100000,激光坐标 42,5842,583232
    为什么答案是 33,就是 2+1=32+1=3,完全符合。所以所有测试案例答案都是 n+mn+m

    那题目为什么给 x,yx,y 范围,以及激光坐标的约束?难道是为了迷惑?
    其实这些条件只是说明激光在矩形内部,不接触边界,保证起点和终点不在激光上。


    检验是否存在小于 n+mn+m 的情况

    我们想,是否存在某条路径,少穿过一次激光?

    假设你从起点直接沿对角线走到终点,它会穿过一些激光。但要想少穿过一条激光,意味着有一条激光你完全没碰到。但激光是贯穿整个矩形对应方向的,你没法绕过它,因为你要从它的一边到另一边,必然穿过它。所以不可能少过。

    因此答案固定为 n+mn+m


    题解结论

    对于每个测试用例:

    • 读入 n,m,x,yn, m, x, y
    • 读入 a1ana_1 \dots a_nb1bmb_1 \dots b_m(实际不需要用到这些坐标的值,只用到 n,mn,m)。
    • 输出 n+mn + m

    标程逻辑

    标程中只是生成随机数据,并不是求解代码,但题目原意是统计 n+mn+m
    真正的解题代码非常简单:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) {
            int n, m;
            long long x, y;
            cin >> n >> m >> x >> y;
            // 读入并丢弃 a[1..n]
            for (int i = 0; i < n; ++i) {
                int tmp;
                cin >> tmp;
            }
            // 读入并丢弃 b[1..m]
            for (int i = 0; i < m; ++i) {
                int tmp;
                cin >> tmp;
            }
            cout << n + m << '\n';
        }
        return 0;
    }
    

    复杂度分析

    • 每个测试用例 O(n+m)O(n + m) 时间。
    • nnmm 分别不超过 2×1052\times 10^5,因此总复杂度 O(n+m)O(\sum n + \sum m)

    最终答案

    每个测试用例的最小穿越次数就是 n+mn + m

    • 1

    信息

    ID
    7275
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    1
    已通过
    1
    上传者