1 条题解

  • 0
    @ 2025-11-21 0:36:19

    这里有一个利用 “虚拟偏移” 技巧来高效解决此问题的方案,它能将每次操作的时间复杂度降至 O(1)

    🔄 关键思路:虚拟偏移

    直接模拟循环右移操作(尤其是当 nq 很大时)非常耗时。关键在于认识到:

    1. 循环右移 k 🔁 等效于序列的起始位置在底层数组中向左移动 k
    2. 我们只需维护一个偏移量 shift 🧭,它记录当前序列第一个元素在原始数组中的实际索引
    3. 所有操作都基于这个 shift 进行坐标转换无需实际移动数组元素

    🧮 坐标转换与总和更新

    • 初始状态shift = 0,当前总和 total_sum 为所有元素之和。
    • 处理指令
      1. 循环右移 k 位 (2 k)
        • 更新偏移量:shift = (shift - k + n) % n。 这里 (shift - k + n) % n 是为了处理负数取模问题,确保结果为非负。
      2. 替换元素 (1 i x)
        • 计算原始数组中的实际索引real_index = (shift + i - 1) % n。 这里 i-1 是因为题目中位置 i 是从1开始的。
        • 更新总和total_sum = total_sum - a[real_index] + x
        • 更新数组a[real_index] = x

    📝 示例演示

    以样例为例,初始数组 a = [4, 1, 2, 1, 5, 3]n=6total_sum=16shift=0

    1. 指令 2 3 (右移3位):
      • shift = (0 - 3 + 6) % 6 = 3
      • 输出 total_sum (16)
    2. 指令 1 3 10 (将新序列第3位改为10):
      • 实际索引 real_index = (3 + 3 - 1) % 6 = 5
      • 更新总和 total_sum = 16 - a[5] + 10 = 16 - 3 + 10 = 23a[5] = 10
      • 输出 23

    🖥️ 代码实现

    以下是基于上述思路的 Python 代码:

    n = int(input())
    a = list(map(int, input().split()))
    q = int(input())
    shift = 0
    total_sum = sum(a)
    
    for _ in range(q):
        operation = list(map(int, input().split()))
        if operation[0] == 2:  # 循环右移
            k = operation[1]
            shift = (shift - k + n) % n
            print(total_sum)
        else:  # 替换元素
            i, x = operation[1], operation[2]
            pos = (shift + i - 1) % n
            total_sum += x - a[pos]
            a[pos] = x
            print(total_sum)
    

    💎 总结

    这道题的核心在于避免直接操作大规模数据,而是通过维护偏移量并进行坐标转换来间接完成。这种“虚拟偏移”的技巧在处理循环数组问题时非常实用。

    • 1

    信息

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