1 条题解
-
0
根据您的要求,以下是该题目的详细题解,所有数字和公式均已使用
$或$$包裹。
题目回顾
给定一个长度为 的序列 。
两人轮流操作:- 乌龟(先手):选择 ,令 ,删除 。
- 小猪(后手):选择 ,令 ,删除 。
直到序列长度变为 ,此时剩下的唯一元素即为最终 。
乌龟希望它尽可能大,小猪希望它尽可能小,双方最优,求最终值。
第一步:问题转化
每次操作减少 个元素,所以总操作次数固定为 次。
乌龟操作 次(因为先手),小猪操作 次。最终剩下的那个元素,实际上是从原序列的 个元素中 “存活” 下来的一个。
问题等价于:双方通过选择合并相邻元素的方式,决定最终留下哪个元素,并且乌龟希望留下大的,小猪希望留下小的。
第二步:关键观察
每一次操作可以看作:
- 乌龟操作: 会把较大的值保留在左边位置。
- 小猪操作: 会把较小的值保留在左边位置。
但是,所有元素都会不断向左“移动”,因为每次删除的都是右边的元素。
最终 的值,一定是原序列中某个元素的值,且这个元素是从原始某个位置经过多次比较后存活下来的。
第三步:必胜/必败思路(简化)
这是一个经典结论题(Codeforces 2042B 类似题)。
可以这样理解:- 乌龟想保留大的数,所以他会尽量让大的数往左走。
- 小猪想保留小的数,所以他会尽量让小的数往左走。
- 最终存活的那个数,是 排序后中间偏右 的一个数。
更精确的结论(经过博弈推导):
将原数组从小到大排序得到 。
答案 = (1-indexed)。即:第 小的数。
第四步:为什么是这个结论
我们考虑一个简化模型:
- 如果把每次合并看作选择两个相邻数中的一个保留到左侧。
- 乌龟会在他的回合让较大的保留,小猪让较小的保留。
- 但由于两人轮流操作,最后的决定权其实落在中间位置的元素上。
数学归纳或逆向思考可知:
当 为奇数时,中间那个元素(第 小)无法被小猪完全压制;
当 为偶数时,第 小的元素是乌龟能保证的最优结果。更严格地,可以用以下方式理解:
假设最终结果是原序列的第 小的数。
那么:- 乌龟希望 尽量大,小猪希望 尽量小。
- 因为乌龟先手且操作次数多一次(当 奇数时),他可以保证 至少是 。
第五步:形式化结论
设 为 排序后的数组,。
则答案为:
或者用 0-indexed 表示(代码中常用):
因为当 为偶数时, 就是第 小的下标(从 0 开始);
当 为奇数时, 向下取整也正确。
第六步:时间复杂度
- 排序
- 总 不超过 ,可通过
第七步:代码实现(C++)
#include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } sort(a.begin(), a.end()); cout << a[n / 2] << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
第八步:验证样例
- ,,, ✅
- ,,, ✅
- ,,, ✅
- → 排序 ,,, ✅
- 第 5 个样例同样得到 ✅
总结
这道题的核心在于:
通过分析双方最优策略,发现最终结果只与排序后的中位数位置有关,
即答案为排序后下标 (0-indexed)的元素。
直接排序后输出即可,无需模拟博弈过程。
- 1
信息
- ID
- 7002
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者