代码实现
# 定义最大数组大小(题目中 N 最大为 10^5)
N = 100010
# 原始数组 w,1-indexed(w[1] ~ w[n] 存储实际数据)
w = [0] * N
# 线段树数组:存储每个节点的区间和
tr_sum = [0] * (4 * N) # 开 4*N 空间是线段树的经典做法,确保不会越界
# 线段树数组:存储每个节点对应的区间左端点 l
tr_l = [0] * (4 * N)
# 线段树数组:存储每个节点对应的区间右端点 r
tr_r = [0] * (4 * N)
def pushup(u):
"""
向上更新:根据左右子节点的值,更新当前节点 u 的区间和。
即:父节点的和 = 左子树和 + 右子树和
"""
tr_sum[u] = tr_sum[u << 1] + tr_sum[u << 1 | 1]
def build(u, l, r):
"""
构建线段树
参数:
u: 当前节点的编号(从 1 开始)
l, r: 当前节点所代表的区间 [l, r](闭区间,1-indexed)
"""
if l == r:
# 叶子节点:区间只有一个元素
tr_l[u] = l # 记录左边界
tr_r[u] = r # 记录右边界
tr_sum[u] = w[r] # 叶子节点的和就是该位置的值(w 是 1-indexed)
else:
# 非叶子节点:需要递归构建左右子树
tr_l[u] = l
tr_r[u] = r
mid = (l + r) // 2 # 分割区间
# 递归构建左子树:节点编号为 u*2,区间 [l, mid]
build(u << 1, l, mid)
# 递归构建右子树:节点编号为 u*2+1,区间 [mid+1, r]
build(u << 1 | 1, mid + 1, r)
# 构建完子树后,向上更新当前节点的和
pushup(u)
def query(u, l, r):
"""
查询区间 [l, r] 的和(1-indexed)
参数:
u: 当前遍历到的线段树节点编号
l, r: 要查询的目标区间
返回:
区间 [l, r] 内所有元素的和
"""
# 如果当前节点所代表的区间 [tr_l[u], tr_r[u]] 完全包含在 [l, r] 内
if tr_l[u] >= l and tr_r[u] <= r:
return tr_sum[u] # 直接返回该节点存储的和,无需继续递归
# 否则,需要拆分到子区间
mid = (tr_l[u] + tr_r[u]) // 2
total = 0
# 如果查询区间的左半部分与左子树有交集(即 l <= mid)
if l <= mid:
total += query(u << 1, l, r) # 递归查询左子树
# 如果查询区间的右半部分与右子树有交集(即 r > mid)
if r > mid:
total += query(u << 1 | 1, l, r) # 递归查询右子树
return total
def modify(u, x, v):
"""
单点修改:将位置 x 的值增加 v(不是赋值!)
参数:
u: 当前节点编号
x: 要修改的位置(1-indexed)
v: 要增加的值
"""
if tr_l[u] == tr_r[u]:
# 到达叶子节点(即位置 x)
tr_sum[u] += v # 增加 v
else:
mid = (tr_l[u] + tr_r[u]) // 2
# 判断 x 在左子树还是右子树
if x <= mid:
modify(u << 1, x, v) # 递归修改左子树
else:
modify(u << 1 | 1, x, v) # 递归修改右子树
# 修改完子树后,向上更新当前节点的和
pushup(u)
# ========== 主程序 ==========
# 读入数字个数 n 和操作次数 m
n, m = map(int, input().split())
# 读入原始数组,并转换为 1-indexed(w[0] 不用,w[1] ~ w[n] 有效)
w = [0] # w[0] = 0(占位)
w.extend(list(map(int, input().split()))) # w[1] 到 w[n] 存入数据
# 从根节点(编号 1)开始,构建覆盖区间 [1, n] 的线段树
build(1, 1, n)
# 存储所有查询结果,避免频繁 print(提高效率)
out_lines = []
# 处理 m 次操作
for _ in range(m):
k, a, b = map(int, input().split())
if k == 0:
# 查询操作:求区间 [a, b] 的和
res = query(1, a, b)
out_lines.append(str(res))
else:
# 修改操作:将位置 a 的值增加 b
modify(1, a, b)
# 输出所有查询结果
for line in out_lines:
print(line)
测试数据
10 5
1 2 3 4 5 6 7 8 9 10
1 1 5
0 1 3
0 4 8
1 7 5
0 4 8
截图
—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com