第3题-待发热度重排

小红书9月17日机考题目与解析

短视频后台里躺着 mm 条待发稿,第 ii 条带着质量分 pip_i 和热度分 hih_i。策划给了一份目标热度排列 t1,t2,…,tmt_1, t_2, \ldots, t_m,要求排完之后每个位置上的热度刚好等于 tt。

运营只能按下面的规则对调两条稿件:当且仅当 pi≤pjp_i \le p_j 且 hi≤hjh_i \le h_j 时,才允许把第 ii 条和第 jj 条互换位置。对调可以做任意多次。

问能否让最终的热度序列与 tt 完全一致。能则输出 YES,不能则输出 NO(大小写必须一致)。

输入描述

第一行一个整数 qq,表示询问组数。(1≤q≤1021 \le q \le 10^2)

接下来 qq 组,每组三行:

  • 第一行一个整数 mm,表示待发条数。(1≤m≤1051 \le m \le 10^5)
  • 第二行 2m2m 个整数,按 p1,h1,p2,h2,…,pm,hmp_1, h_1, p_2, h_2, \ldots, p_m, h_m 给出每条稿的质量分与热度分。(1≤pi,hi≤1051 \le p_i, h_i \le 10^5)
  • 第三行 mm 个整数 tit_i,即目标热度排列。(1≤ti≤1051 \le t_i \le 10^5)

保证全部询问的 mm 之和不超过 10610^6。

输出描述

对每组询问输出一行 YES 或 NO。

样例 1

输入:

3
2
1 1 2 3
3 1
2
1 5 2 1
1 5
3
1 4 2 1 3 5
1 4 5

输出:

YES
NO
YES

说明: - 第一组:(1,1)(1,1) 与 (2,3)(2,3) 可以互换,热度能变成 313\ 1。 - 第二组:(1,5)(1,5) 与 (2,1)(2,1) 互不可比,对调不了,热度变不成 151\ 5。 - 第三组:三条都能经由可比对调连成一块,热度多重集与目标相同,故可以重排。

样例 2

输入:

2
1
7 7
7
3
1 5 2 3 3 1
1 3 5

输出:

YES
NO

说明: - 第一组:只有一条,热度已是 77。 - 第二组:质量升、热度降,两两不可比,只能保持 5315\ 3\ 1,对不齐 1351\ 3\ 5。

思路

按 (p,h)(p, h) 双关键字排序后,位置 ii 在 jj 前面则必有 pi≤pjp_i \le p_j,于是「可交换」当且仅当 hi≤hjh_i \le h_j。

考察相邻两段 [0,r][0, r] 与 [r+1,m)[r+1, m):

  • 若前缀的最小热度 ≤\le 后缀的最大热度(pre_min[r] <= suf_max[r+1]),则存在跨段的可比对,两段连通;
  • 若前缀最小严格大于后缀最大,则任何跨段对的 hh 都是「左大右小」,不可交换——这是一个不可跨越的分割点。

据此把序列切成若干块:块内热度可以任意重排,块与块之间完全隔离。答案为 YES 当且仅当每一块内热度的多重集与目标 tt 对应段一致(排序后逐块比较)。前缀最小 / 后缀最大用 itertools.accumulate 一遍预处理,总复杂度 O(mlog⁡m)O(m \log m)。

代码

from itertools import accumulate

def solve():
    m = int(input())
    vals = list(map(int, input().split()))
    p = vals[0::2]
    h = vals[1::2]
    t = list(map(int, input().split()))

    # 按 (p, h) 排序
    order = sorted(range(m), key=lambda i: (p[i], h[i]))
    hs = [h[i] for i in order]
    ts = [t[i] for i in order]

    # 前缀最小、后缀最大
    pre_min = list(accumulate(hs, min))
    suf_max = list(accumulate(reversed(hs), max))[::-1]

    l = 0
    while l < m:
        r = l
        while r + 1 < m and pre_min[r] <= suf_max[r + 1]:
            r += 1

        if sorted(hs[l:r + 1]) != sorted(ts[l:r + 1]):
            return "NO"
        l = r + 1

    return "YES"


q = int(input())
for _ in range(q):
    print(solve())

第3题-待发热度重排
https://mingsm17518.github.io/2026/11/03/刷题笔记/机考/小红书/2026年9月17日/第3题-待发热度重排/
作者
Ming
发布于
2026年11月3日
更新于
2026年11月3日
许可协议