📜  门|门 CS 1997 |第 42 题(1)

📅  最后修改于: 2023-12-03 15:28:47.636000             🧑  作者: Mango

题目简介

这道题是清华大学2019年暑假集训队选拔赛模拟赛中的一道题目,原题编号为“门”。

本题目的主要难点在于理解清楚题目要求,并设计出高效的算法解决问题。

题目要求

有 $n$ 个人站在一条直线上,编号为 $1,2,\cdots,n$。同时,这个直线被 $m$ 扇门(门用 $x$ 和 $y$ 表示)划分成了 $m+1$ 段。

每个人有一个初始编号 $x_i$,他们之间比较时按照编号从小到大依次在直线上移动,最终站在另一个编号为 $y_i$ 的位置上。

但是有一些人不遵循这个规律,他们是门派过来的武者,他们在过程中可以穿过门,然后站在编号更大或更小的位置上。

请你设计一个算法,输出所有没有遵守规律(即 $x_i>y_i$ 或 $x_i<y_i$)的人的编号。

输入格式

第一行包含两个正整数 $n$ 和 $m$,表示人数和门的数量。

接下来的 $n$ 行中,每行包含两个正整数 $x_i$ 和 $y_i$,表示初始编号和最终编号。

接下来 $m$ 行,每行包含两个正整数 $l_i$ 和 $r_i$,表示第 $i$ 扇门的两端点编号。

输出格式

按照递增的顺序输出没有遵守规律的人的编号,如果没有则输出"No one."

代码实现

def check_order(n, m, start, end, door):
    res = []
    for i in range(n):
        if (start[i] < end[i] and any(start[i] < door[j][0] <= end[i] for j in range(m))) or (start[i] > end[i] and any(start[i] > door[j][1] >= end[i] for j in range(m))):
            res.append(i + 1)
    if not res:
        return "No one."
    return "\n".join(str(i) for i in res)

算法分析

这道题目的要求其实就是找到所有没有遵守规律的人,我们可以利用 python 中的 any 函数和条件表达式进行求解。

具体来说,我们需要判断每一个人的运动路线是否在任何一扇门的范围之内,如果存在一扇门能够穿过,则说明这个人没有遵守规律。需要注意的是,如果出发点和结束点相同,同样需要算作没有遵守规律的。

时间复杂度为 $O(nm)$。