1 条题解
-
0
题意理解
- 有一个长度为 (n) 的未知排列 (P)。
- 每次可以询问一个排列 (R),交互库返回 在 (P) 中 (i) 在 (j) 前面,但在 (R) 中 (i) 在 (j) 后面 的有序对 ((i,j)) 的数量。
- 换句话说,返回的是 两个排列中相对顺序不同的逆序对数量,更准确地说,是 满足 (pos_P(i) < pos_P(j)) 且 (pos_R(i) > pos_R(j)) 的 ((i,j)) 对数。
- 最多询问 4000 次,要猜出 (P)。
关键转化
设 (inv(P,R)) 表示上述返回值。
一个重要观察:
- 如果 (R) 是 (P) 的逆排列,则 (inv(P,R) = \frac{n(n-1)}{2})(所有对都反序)。
- 如果 (R = P),则 (inv(P,R) = 0)(完全一致)。
更一般地,(inv(P,R)) 衡量了两个排列的 不一致程度。
核心思路
我们可以通过固定一个元素的位置,测试它与其他元素的相对顺序。
方法:逐个确定位置
-
确定第一个位置
我们可以把某个元素 (x) 放在 (R) 的第一个位置,其他元素任意排(比如按编号升序)。
询问得到 (inv(P,R))。
这个值的大小与 (x) 在 (P) 中的位置有关吗?
实际上,如果 (x) 在 (P) 中越靠前,那么把它放到 (R) 的第一位时,与 (P) 的相对顺序变化不大,(inv) 值较小;
如果 (x) 在 (P) 中很靠后,那么把它提前到第一位会导致很多对 ((x, j)) 的顺序翻转,(inv) 值较大。更具体地:
设 (pos_P(x) = k)(从 0 开始计数)。
当 (R) 中 (x) 在第一位,其他按 (1,2,\dots,n) 升序排列时:- 对于 (P) 中在 (x) 前面的元素(有 (k) 个),在 (R) 中它们都在 (x) 后面,所以这些对 ((y,x)) 在 (P) 中是 (y) 在 (x) 前,在 (R) 中是 (y) 在 (x) 后,贡献 (k) 个逆序对。
- 对于 (P) 中在 (x) 后面的元素(有 (n-1-k) 个),在 (R) 中它们都在 (x) 后面,顺序一致,不贡献。
所以 (inv = k)。
这样一次询问就能确定 (x) 在 (P) 中的位置 (k)。
-
确定所有元素的位置
对每个元素 (x),做一次上述询问,就能知道 (pos_P(x))。
需要 (n) 次询问。
询问构造
对于元素 (x),构造 (R):
- (R[0] = x)
- 其余位置按编号升序填入 (1,2,\dots,n)(跳过 (x))
调用
publish(R)得到 (inv),则 (pos_P(x) = inv)。
复杂度分析
- 询问次数:(n) 次(每个元素一次)
- (n \le 4000),远小于 4000 次限制
- 时间复杂度:(O(n^2)) 构造排列(简单实现),可优化到 (O(n)) 每次
正确性证明
为什么 (inv = pos_P(x))?
- 在 (P) 中,有 (pos_P(x)) 个元素在 (x) 前面。
- 在 (R) 中,这些元素都在 (x) 后面。
- 所以这些元素与 (x) 的相对顺序在 (P) 和 (R) 中相反,贡献 (pos_P(x)) 个逆序对。
- 其他元素与 (x) 的相对顺序在 (P) 和 (R) 中相同(都在 (x) 后面),不贡献。
- 其他元素之间的相对顺序在 (R) 中是升序,与 (P) 中可能不同,但题目只统计 在 (P) 中 (i) 在 (j) 前,在 (R) 中 (i) 在 (j) 后 的对,而 (R) 中非 (x) 部分是升序,所以如果 (P) 中这部分有逆序,也不会被统计(因为 (P) 中 (i) 在 (j) 前,(R) 中 (i) 也在 (j) 前,不满足条件)。
因此返回值严格等于 (pos_P(x))。
总结
这道题的关键在于 通过将某个元素放到排列首位,其余按固定顺序排列,利用返回值直接得到该元素在目标排列中的位置。
这是一种巧妙的位置编码方法,将排列还原问题转化为 (n) 次独立的位置查询。
- 1
信息
- ID
- 4296
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者