1 条题解

  • 0
    @ 2026-5-7 19:59:24

    根据您的要求,以下是该题目的详细题解,所有数字和公式均已使用 $$$ 包裹。


    题目回顾

    给定一个长度为 nn 的序列 a1,a2,,ana_1, a_2, \dots, a_n
    两人轮流操作:

    • 乌龟(先手):选择 ii,令 ai=max(ai,ai+1)a_i = \max(a_i, a_{i+1}),删除 ai+1a_{i+1}
    • 小猪(后手):选择 ii,令 ai=min(ai,ai+1)a_i = \min(a_i, a_{i+1}),删除 ai+1a_{i+1}

    直到序列长度变为 11,此时剩下的唯一元素即为最终 a1a_1
    乌龟希望它尽可能大,小猪希望它尽可能小,双方最优,求最终值。


    第一步:问题转化

    每次操作减少 11 个元素,所以总操作次数固定为 n1n-1 次。
    乌龟操作 n12 \lceil \frac{n-1}{2} \rceil 次(因为先手),小猪操作 n12 \lfloor \frac{n-1}{2} \rfloor 次。

    最终剩下的那个元素,实际上是从原序列的 nn 个元素中 “存活” 下来的一个。
    问题等价于:双方通过选择合并相邻元素的方式,决定最终留下哪个元素,并且乌龟希望留下大的,小猪希望留下小的。


    第二步:关键观察

    每一次操作可以看作:

    • 乌龟操作:max(x,y)\max(x, y) 会把较大的值保留在左边位置。
    • 小猪操作:min(x,y)\min(x, y) 会把较小的值保留在左边位置。

    但是,所有元素都会不断向左“移动”,因为每次删除的都是右边的元素。
    最终 a1a_1 的值,一定是原序列中某个元素的值,且这个元素是从原始某个位置经过多次比较后存活下来的。


    第三步:必胜/必败思路(简化)

    这是一个经典结论题(Codeforces 2042B 类似题)。
    可以这样理解:

    • 乌龟想保留大的数,所以他会尽量让大的数往左走。
    • 小猪想保留小的数,所以他会尽量让小的数往左走。
    • 最终存活的那个数,是 排序后中间偏右 的一个数。

    更精确的结论(经过博弈推导):

    将原数组从小到大排序得到 b1b2bnb_1 \le b_2 \le \dots \le b_n
    答案 = bn/2+1b_{\lfloor n/2 \rfloor + 1} (1-indexed)。

    即:n/2+1\lfloor n/2 \rfloor + 1 小的数


    第四步:为什么是这个结论

    我们考虑一个简化模型:

    • 如果把每次合并看作选择两个相邻数中的一个保留到左侧。
    • 乌龟会在他的回合让较大的保留,小猪让较小的保留。
    • 但由于两人轮流操作,最后的决定权其实落在中间位置的元素上。

    数学归纳或逆向思考可知:
    nn 为奇数时,中间那个元素(第 (n+1)/2(n+1)/2 小)无法被小猪完全压制;
    nn 为偶数时,第 n/2+1n/2 + 1 小的元素是乌龟能保证的最优结果。

    更严格地,可以用以下方式理解:

    假设最终结果是原序列的第 kk 小的数。
    那么:

    • 乌龟希望 kk 尽量大,小猪希望 kk 尽量小。
    • 因为乌龟先手且操作次数多一次(当 nn 奇数时),他可以保证 kk 至少是 n/2+1\lfloor n/2 \rfloor + 1

    第五步:形式化结论

    bbaa 排序后的数组,b1b2bnb_1 \le b_2 \le \dots \le b_n

    则答案为:

    bn/2+1\boxed{b_{\lfloor n/2 \rfloor + 1}}

    或者用 0-indexed 表示(代码中常用):

    answer=b[n/2]\text{answer} = b[n/2]

    因为当 nn 为偶数时,n/2n/2 就是第 n/2+1n/2+1 小的下标(从 0 开始);
    nn 为奇数时,n/2n/2 向下取整也正确。


    第六步:时间复杂度

    • 排序 O(nlogn)O(n \log n)
    • nn 不超过 10510^5,可通过

    第七步:代码实现(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;
    }
    

    第八步:验证样例

    1. [1,2][1,2]n=2n=2n/2=1n/2=1b1=2b_1=2
    2. [1,1,2][1,1,2]n=3n=3n/2=1n/2=1b1=1b_1=1
    3. [1,2,3][1,2,3]n=3n=3n/2=1n/2=1b1=2b_1=2
    4. [3,1,2,2,3][3,1,2,2,3] → 排序 [1,2,2,3,3][1,2,2,3,3]n=5n=5n/2=2n/2=2b2=2b_2=2
    5. 第 5 个样例同样得到 77

    总结

    这道题的核心在于:
    通过分析双方最优策略,发现最终结果只与排序后的中位数位置有关,
    即答案为排序后下标 n/2\lfloor n/2 \rfloor(0-indexed)的元素。
    直接排序后输出即可,无需模拟博弈过程。

    • 1

    信息

    ID
    7002
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    1
    已通过
    1
    上传者