1 条题解

  • 0
    @ 2025-11-11 8:57:02

    题目分析

    我们有一个初始字符串 SS,然后进行 NN 次复制粘贴操作:

    • ii 次操作:复制 [Ai,Bi)[A_i, B_i) 区间的子串,插入到位置 CiC_i
    • 字符串长度不能超过 MM,超过时从末尾删除
    • 最终需要输出前 KK 个字符

    关键限制K200K \leq 200MM 可达 10910^9NN 可达 2×1052\times 10^5

    核心难点

    如果直接模拟操作,字符串长度可能变得非常巨大(理论上可达 M=109M = 10^9),这显然不可行。

    关键观察:我们只需要知道最终字符串的前 KK 个字符,而不需要维护整个字符串。

    逆向思维解法

    我们可以从后往前逆向处理操作,追踪前 KK 个字符的来源。

    逆向处理思路

    pos[i] 表示最终的第 ii 个字符在操作前的来源位置(在哪个字符串的哪个位置)。

    从最后一次操作开始,倒推到初始字符串:

    对于每个操作 (A,B,C)(A, B, C)

    • 这个操作将区间 [A,B)[A, B) 复制插入到位置 CC
    • 在逆向处理时,我们需要知道当前考虑的字符在操作前来自哪里

    字符来源分类

    对于位置 xx(0-based):

    1. 在插入点之前x<Cx < C → 来源位置不变:xx
    2. 在插入的块内Cx<C+(BA)C \leq x < C + (B - A) → 来源位置为:A+(xC)A + (x - C)
      (来自被复制的原区间)
    3. 在插入点之后但受挤压xC+(BA)x \geq C + (B - A) → 来源位置为:x(BA)x - (B - A)
      (因为插入导致原位置后移)

    但是要注意:由于长度限制 MM,有些字符可能被截断,我们只关心前 KK 个字符。

    算法步骤

    1. 初始化 pos[0..K-1]0..K10..K-1(最终的前 KK 个字符最初就是自己)
    2. 从最后一个操作到第一个操作逆向处理:
      • 对于每个 i[0,K1]i \in [0, K-1],根据 pos[i] 判断它在当前操作前的来源
      • 更新 pos[i]
    3. 处理完所有操作后,pos[i] 就是第 ii 个字符在初始字符串 SS 中的位置
    4. 如果 pos[i] < len(S),输出 S[pos[i]]S[pos[i]],否则说明这个位置在初始字符串之外(由后续操作生成)

    边界情况处理

    • 如果逆向过程中发现 pos[i] 超过了当时字符串的长度,说明这个字符在操作前不存在(是后续操作产生的)
    • 由于我们只关心前 KK 个字符,当插入位置 C>KC > K 时,这个操作对前 KK 个字符没有影响

    总结

    这道题的核心技巧是:

    1. 逆向思维:从结果反推来源
    2. 局部求解:只关心需要的部分(前 KK 个字符)
    3. 位置追踪:通过维护位置映射关系避免处理整个字符串

    这种"逆向处理 + 位置追踪"的技巧在解决大规模字符串操作问题时非常有用,特别是当直接模拟不可行时。

    • 1

    信息

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