1 条题解

  • 0
    @ 2026-6-19 10:30:05

    📝 题目大意

    NN 个格子排成一行,KK 个棋子初始放在 A1<A2<<AKA_1 < A_2 < \dots < A_K 的位置上。进行 QQ 次操作,每次操作指定从左到右第 LiL_i 个棋子:若该棋子不在最右格且右侧相邻格为空,则向右移动一格;否则不动。输出最终每个棋子的位置。

    💡 解题思路

    1. 题目分析

      • N,K200N, K \le 200Q1000Q \le 1000,数据范围很小,直接模拟即可。
      • 棋子初始位置严格递增 (A1<A2<<AKA_1 < A_2 < \dots < A_K),且每次移动只会向右,因此棋子的相对顺序永远不会改变——第 LL 个棋子始终是第 LL 个棋子。
      • 由于棋子不会跨越彼此,"右侧相邻格为空"等价于"第 LL 个棋子不在第 L+1L+1 个棋子的紧左边"。
    2. 算法推导

      • 用数组 pos[1..K] 存储每个棋子的位置(1-indexed,与输入的第 LL 个棋子对应)。
      • 对每次操作 LL,分三种情况判断:
        • 已在最右格pos[L] == N → 跳过。
        • 右侧相邻格被占L<KL < Kpos[L] + 1 == pos[L+1] → 跳过(因为棋子按顺序排列,只有紧右边的棋子会阻挡)。
        • 可以移动pos[L]++
      • 注意当 L=KL = K(最后一个棋子)时,没有右边的棋子,只需检查是否在边界 NN
    3. 边界与细节

      • 数组下标从 1 开始,与输入 LiL_i 直接对应,避免偏移转换。
      • 操作过程中棋子位置始终保持递增,不需要额外维护。
      • 输出时用空格分隔,末尾换行。

    ⏱️ 复杂度分析

    • 时间复杂度O(K+Q)O(K + Q),每次操作 O(1)O(1) 判断与移动。
    • 空间复杂度O(K)O(K),仅存储棋子位置数组。

    💻 标准代码 (C++)

    #include<bits/stdc++.h>
    using namespace std;
    int main() {
        int N, K, Q;
        cin >> N >> K >> Q;
        vector<int> pos(K + 1);     // 1-indexed,pos[i] 表示从左到右第 i 个棋子的位置
        for (int i = 1; i <= K; i++) {
            cin >> pos[i];          // 读入初始位置,已保证递增
        }
        for (int i = 0; i < Q; i++) {
            int L;
            cin >> L;
            // 情况1:已在最右格,无法移动
            if (pos[L] == N) {
                continue;
            }
            // 情况2:右侧紧邻的格子被第 L+1 个棋子占据
            // 注意 L == K 时没有右边的棋子,跳过此判断
            if (L < K && pos[L] + 1 == pos[L + 1]) {
                continue;
            }
            // 情况3:可以向右移动一格
            pos[L]++;
        }
        // 输出最终结果
        for (int i = 1; i <= K; i++) {
            cout << pos[i] << (i < K ? " " : "\n");
        }
        return 0;
    }
    
    • 1

    信息

    ID
    606
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者