1 条题解
-
0
这里有一个利用 “虚拟偏移” 技巧来高效解决此问题的方案,它能将每次操作的时间复杂度降至 O(1)。
🔄 关键思路:虚拟偏移
直接模拟循环右移操作(尤其是当
n和q很大时)非常耗时。关键在于认识到:- 循环右移
k位 🔁 等效于序列的起始位置在底层数组中向左移动k位。 - 我们只需维护一个偏移量
shift🧭,它记录当前序列第一个元素在原始数组中的实际索引。 - 所有操作都基于这个
shift进行坐标转换,无需实际移动数组元素。
🧮 坐标转换与总和更新
- 初始状态:
shift = 0,当前总和total_sum为所有元素之和。 - 处理指令:
- 循环右移
k位 (2 k):- 更新偏移量:
shift = (shift - k + n) % n。 这里(shift - k + n) % n是为了处理负数取模问题,确保结果为非负。
- 更新偏移量:
- 替换元素 (
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=6,total_sum=16,shift=0。- 指令
2 3(右移3位):shift = (0 - 3 + 6) % 6 = 3- 输出
total_sum(16)
- 指令
1 3 10(将新序列第3位改为10):- 实际索引
real_index = (3 + 3 - 1) % 6 = 5 - 更新总和
total_sum = 16 - a[5] + 10 = 16 - 3 + 10 = 23,a[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
- 上传者