第3题-待发热度重排
小红书9月17日机考题目与解析
短视频后台里躺着 条待发稿,第 条带着质量分 和热度分 。策划给了一份目标热度排列 ,要求排完之后每个位置上的热度刚好等于 。
运营只能按下面的规则对调两条稿件:当且仅当 且 时,才允许把第 条和第 条互换位置。对调可以做任意多次。
问能否让最终的热度序列与
完全一致。能则输出 YES,不能则输出
NO(大小写必须一致)。
输入描述
第一行一个整数 ,表示询问组数。()
接下来 组,每组三行:
- 第一行一个整数 ,表示待发条数。()
- 第二行 个整数,按 给出每条稿的质量分与热度分。()
- 第三行 个整数 ,即目标热度排列。()
保证全部询问的 之和不超过 。
输出描述
对每组询问输出一行 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说明: - 第一组: 与 可以互换,热度能变成 。 - 第二组: 与 互不可比,对调不了,热度变不成 。 - 第三组:三条都能经由可比对调连成一块,热度多重集与目标相同,故可以重排。
样例 2
输入:
2
1
7 7
7
3
1 5 2 3 3 1
1 3 5输出:
YES
NO说明: - 第一组:只有一条,热度已是 。 - 第二组:质量升、热度降,两两不可比,只能保持 ,对不齐 。
思路
按 双关键字排序后,位置 在 前面则必有 ,于是「可交换」当且仅当 。
考察相邻两段 与 :
- 若前缀的最小热度
后缀的最大热度(
pre_min[r] <= suf_max[r+1]),则存在跨段的可比对,两段连通; - 若前缀最小严格大于后缀最大,则任何跨段对的 都是「左大右小」,不可交换——这是一个不可跨越的分割点。
据此把序列切成若干块:块内热度可以任意重排,块与块之间完全隔离。答案为
YES 当且仅当每一块内热度的多重集与目标
对应段一致(排序后逐块比较)。前缀最小 / 后缀最大用
itertools.accumulate 一遍预处理,总复杂度
。
代码
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题-待发热度重排/