1 条题解

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

    📝 题目大意

    NN 个整数 1N1 \sim N 排成一列,其中有 MM 个"レ"连接相邻整数(第 ii 个"レ"连接 aia_iai+1a_i+1)。阅读规则:每次选取未读的最小整数 xx,找到包含 xx 的连通分量,将该分量内所有整数从大到小读出。求最终的阅读顺序。

    💡 解题思路

    1. 题目分析

      • N100N \leq 100,数据范围极小,O(N2)O(N^2) 甚至 O(N3)O(N^3) 均可通过。
      • 由于"レ"只连接相邻整数(aia_iai+1a_i+1),图的连通分量必然是原序列上连续的一段区间。这是简化问题的关键隐藏条件。
      • 当按"每次选最小未读数"操作时,等价于从左到右处理每个连通块,每个块内部从大到小输出。
    2. 算法推导

      • 用一个布尔数组 a[110] 标记:a[x] = 1 表示 xxx+1x+1 之间有一条"レ"边。
      • 从左到右扫描 1N1 \sim N,用变量 s 记录当前连续"レ"的个数(即当前连通块中边的数量):
        • a[i] == 1:说明 iii+1i+1 属于同一连通块,s++
        • a[i] == 0:说明当前连通块在 ii 处结束,该块的范围是 [is, i][i-s,\ i](共 s+1s+1 个元素),从 ii 倒序输出到 isi-s;然后 s = 0 重置。
      • 举例:a=[1,3,4]a = [1,3,4] 时,a[1]=a[3]=a[4]=1。扫描到 i=2i=2a[2]=0)时 s=1s=1,输出 2,12,1;扫描到 i=5i=5s=2s=2,输出 5,4,35,4,3
    3. 边界与细节

      • M=0M=0a 数组全为 00,每个 ii 都触发输出,ss 始终为 00,输出 ii 自身,即 1,2,,N1,2,\dots,N。代码自然处理。
      • 相邻"レ"连续(如 a=[1,2,3]a=[1,2,3]):ss 会累加到 33,在 i=4i=4 处一次性输出 4,3,2,14,3,2,1,正确。
      • 注意数组大小:N100N \leq 100,开到 110110 足够。

    ⏱️ 复杂度分析

    • 时间复杂度O(N)O(N),仅需一次线性扫描。
    • 空间复杂度O(N)O(N),仅需一个标记数组。

    💻 标准代码 (C++)

    #include<bits/stdc++.h>
    using namespace std;
    int n, m, x, s, z, a[110];
    int main(){
        cin >> n >> m;
        // 标记"レ"的位置:a[x]=1 表示 x 与 x+1 之间有一条边
        for(int i = 0; i < m; i++){
            cin >> x;
            a[x] = 1;
        }
        // 从左到右扫描,s 表示当前连通块中连续边的数量
        for(int i = 1; i <= n; i++){
            if(a[i] != 0)
                s++;               // 边还在延续,累加
            else{
                // 当前连通块到此结束,范围 [i-s, i],倒序输出
                for(int j = i; j >= i - s; j--){
                    cout << j << " ";
                }
                s = 0;             // 重置,准备下一个连通块
            }
        }
        return 0;
    }
    
    • 1

    信息

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