Skip to content

哈喵~!各位看官,今天我们来解决一道非常可爱的逻辑题,A. Race!这道题就像是在和 Alice 玩一个追逐游戏,我们要帮 Bob 找到一个必胜的位置,是不是很有趣呀?喵~

题目大意

简单来说,就是 Alice 和 Bob 在一条直线上赛跑抢夺奖品的故事,喵。

  • Alice 的起点是固定的,在位置 a
  • 奖品 可能会出现在两个位置中的一个:x 或者 y
  • Bob 需要选择一个整数点 b 作为他的起点(但是 b 不能和 Alice 的起点 a 相同)。

我们的任务是,判断 Bob 能否找到这样一个起点 b,使得无论奖品出现在 x 还是 y,Bob 到奖品的距离都严格小于 Alice 到奖品的距离。

两个点 cd 之间的距离就是 |c - d| 啦。

如果 Bob 能找到这样的必胜起点,我们就输出 "YES",否则就输出 "NO",喵。

题解方法

这道题的核心在于理解 Bob 的“必胜”条件。他需要找到一个点 b,同时满足下面两个不等式:

  1. |b - x| < |a - x| (如果奖品在 x,Bob 比 Alice 更近)
  2. |b - y| < |a - y| (如果奖品在 y,Bob 比 Alice 更近)

让我们把这个问题放到一维的数轴上来思考,这样就直观多啦,喵~

为了方便分析,我们可以先对 xy 的位置进行排序。比如说,我们总是假设 x < y。如果输入的 x > y,我们只要把它们交换一下,问题本质是完全一样的,但我们的思考过程可以简化不少哦!

现在,我们有了 x < y 这个前提,再来考虑 Alice 的位置 axy 的相对关系。这里就出现了两种主要情况:

情况一:Alice 的起点 a 在两个奖品点 xy 之间 (也就是 x < a < y)

  • 想象一下,xa 的左边,ya 的右边。
  • 为了比 Alice 更靠近 x,Bob 必须选择一个在 a 左侧,并且离 x 更近的点。这些点都在 xa 的中点 (x+a)/2 的左边。
  • 为了比 Alice 更靠近 y,Bob 必须选择一个在 a 右侧,并且离 y 更近的点。这些点都在 ya 的中点 (y+a)/2 的右边。

Bob 需要同时满足这两个条件,但是一个点 b 不可能同时在 a 的左边和右边呀!所以,如果 Alice 处在 xy 中间,她就像一个守门员,把通往两个奖品的近路都给分开了。Bob 找不到任何一个位置 b 能同时满足两个条件。所以这种情况下,答案是 "NO",喵呜~。

情况二:Alice 的起点 a 在两个奖品点 xy 的外侧

因为我们已经假设了 x < y,所以这种情况就包含了 a < x < yx < y < a 两种。

  • 如果 a < x < y: 两个奖品点都在 Alice 的右边。Alice 要跑去 x 或者 y,都得往右跑。Bob 只要选择一个在 Alice 和奖品之间的位置,比如 b = x,就可以占得先机啦!
    • 当奖品在 x,Bob 的距离是 |x - x| = 0,Alice 的距离是 |a - x| > 0。Bob 赢!
    • 当奖品在 y,Bob 的距离是 |x - y|,Alice 的距离是 |a - y|。因为 a < x < y,所以 xa 更靠近 y,所以 |x - y| < |a - y|。Bob 又赢了!
  • 如果 x < y < a: 两个奖品点都在 Alice 的左边。情况和上面类似,Bob 只要选择一个在 Alice 和奖品之间的位置,比如 b = y,也一定能赢。

在这两种子情况下,Bob 总能找到一个必胜点。所以,只要 Alice 不在 xy 之间,答案就是 "YES",喵!

总结一下我们的策略就是:

  1. 为了方便,先让 x 成为 xy 中较小的那个。
  2. 判断 a 是否在 xy 之间。
  3. 如果在,就是 "NO";如果不在,就是 "YES"。

是不是很简单呀?喵~

题解

下面是这个思路的 C++ 实现代码,加上了猫娘的专属注释哦!

cpp
#include <iostream>
#include <algorithm> // 用来调用 std::swap,很方便喵
#include <cmath>     // 用来调用 abs,虽然这里用不到,但是好习惯!

void solve() {
    int a, x, y;
    std::cin >> a >> x >> y;

    // 为了方便,我们让 x 总是比 y 小喵~
    // 这样就不用分 x<y 和 y<x 两种情况讨论啦
    if (x > y) {
        std::swap(x, y);
    }

    // 现在我们能保证 x <= y
    // 根据我们上面的分析,只要 Alice 不在两个奖品点之间,Bob 就有必胜策略
    // a > x && a < y 就表示 a 在 x 和 y 之间(因为题目保证了 a,x,y 两两不同)
    if (a > x && a < y) {
        // Alice 守住了中间,Bob 没办法两头兼顾,好可惜喵...
        std::cout << "NO\n";
    } else {
        // Alice 在外侧,Bob 可以轻松找到一个好位置!耶!
        std::cout << "YES\n";
    }
}

int main() {
    // 这两行是加速输入输出的魔法,对付大数据量很有用喵
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    int t;
    std::cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

知识点介绍

这道题虽然简单,但背后也藏着一些有用的知识点呢,喵!

  1. 绝对值与数轴距离 (Absolute Value and Distance on a Number Line) 题目中的距离 |c - d| 是一个基础但非常重要的数学概念。它表示在数轴上点 c 和点 d 之间的距离。理解这一点是解决所有一维坐标问题的基础。

  2. 分类讨论 (Casework) 这是算法竞赛中一种极其常用的思想。当一个问题看起来比较复杂时,我们可以根据输入数据的某些关键性质将其分解为几个更简单、更清晰的子问题。在这道题里,我们就是根据 a 相对于 xy 的位置(在中间还是在外侧)进行了分类,从而让问题迎刃而解。

  3. 简化问题 (Problem Simplification) 通过 std::swap 操作,我们确保了 x <= y。这并不是必须的,但它能让我们的逻辑判断变得更简单(从 (a > x && a < y) || (a > y && a < x) 简化为 a > x && a < y)。在解决问题时,先对输入进行预处理或规范化,常常能大大降低代码的复杂性,减少出错的可能,是个非常好的习惯喵!

希望这篇题解对你有帮助喵!如果还有其他问题,随时可以再来找我哦!下次再见啦~ (ฅ'ω'ฅ)

Released under the MIT License.