📅  最后修改于: 2023-12-03 14:58:22.150000             🧑  作者: Mango
这是 GATE CS 2021 设置1 问题16 的介绍,它实际上是一道编程题。
给定一个包含 n
个正整数的列表,您需要实现以下操作:
UPDATE i val
:将列表中索引 i
处的数更新为 val
。QUERY l r
:询问列表中 [l, r]
区间内的数之和。在给定的列表上执行多个操作,您需要输出每个查询操作的答案。
输入的第一行包含一个整数 n
,表示列表中元素个数。
接下来的一行包含 n
个整数,表示列表中的元素。
接下来的一行包含一个整数 q
,表示要执行的操作次数。
接下来的 q
行描述每次操作,每次操作可能是以下两种之一:
UPDATE i val
:表示对索引 i
执行更新操作,将其值设置为 val
(1 <= i <= n,1 <= val <= 10^9)。QUERY l r
:表示对列表 [l, r]
进行查询操作,返回其和(1 <= l <= r <= n)。对每个查询操作,输出它的结果。
3
1 2 3
3
QUERY 1 3
UPDATE 2 4
QUERY 1 3
6
8
该问题可以通过使用线段树来解决。构建线段树之后,对于每个更新和查询操作,我们可以在 log(n) 时间内完成。
下面是使用 Python 3 编写的解决方案的示例代码:
# 定义节点类
class Node:
def __init__(self, left, right):
self.left = left
self.right = right
self.sum = 0
self.lazy = None
# 定义线段树类
class SegmentTree:
def __init__(self, array):
self.array = array
self.tree = self.build(1, 0, len(self.array) - 1)
# 构建线段树
def build(self, node, left, right):
if left == right:
return Node(left, right)
mid = left + (right - left) // 2
left_node = self.build(node * 2, left, mid)
right_node = self.build(node * 2 + 1, mid + 1, right)
node = Node(left, right)
node.sum = left_node.sum + right_node.sum
return node
# 更新操作
def update(self, node, index, value):
if node is None:
return
if node.left == index and node.right == index:
node.sum = value
node.lazy = None
return
if node.lazy is not None:
self.propagate(node)
mid = node.left + (node.right - node.left) // 2
if index <= mid:
self.update(node.left_child, index, value)
else:
self.update(node.right_child, index, value)
node.sum = node.left_child.sum + node.right_child.sum
# 查询操作
def query(self, node, left, right):
if node is None:
return 0
if node.lazy is not None:
self.propagate(node)
if node.left == left and node.right == right:
return node.sum
mid = node.left + (node.right - node.left) // 2
if right <= mid:
return self.query(node.left_child, left, right)
if left > mid:
return self.query(node.right_child, left, right)
return self.query(node.left_child, left, mid) + self.query(node.right_child, mid + 1, right)
# 延迟更新操作
def propagate(self, node):
if node.lazy is None:
return
node.left_child.lazy = node.lazy
node.left_child.sum = node.lazy * (node.left_child.right - node.left_child.left + 1)
node.right_child.lazy = node.lazy
node.right_child.sum = node.lazy * (node.right_child.right - node.right_child.left + 1)
node.lazy = None
# 带有延迟更新操作的更新操作
def update_with_lazy(self, node, left, right, value):
# 区间包含,直接更新
if node.left == left and node.right == right:
node.sum = value * (right - left + 1)
node.lazy = value
return
# 如果存在lazy值,需要先处理一下
if node.lazy is not None:
self.propagate(node)
mid = node.left + (node.right - node.left) // 2
# 如果查询区间在当前兄弟结点的左边,向左递归查询
if right <= mid:
self.update_with_lazy(node.left_child, left, right, value)
# 如果查询区间在当前兄弟结点的右边,向右递归查询
elif left > mid:
self.update_with_lazy(node.right_child, left, right, value)
# 如果查询区间横跨左右两个兄弟结点,分别向左右递归查询
else:
self.update_with_lazy(node.left_child, left, mid, value)
self.update_with_lazy(node.right_child, mid + 1, right, value)
# 回溯时需要更新sum值
node.sum = node.left_child.sum + node.right_child.sum
# 输入元素个数n,以及每个元素的值
n = int(input())
array = list(map(int, input().split()))
# 构建线段树
tree = SegmentTree(array)
# 输入操作个数q,以及每个操作
q = int(input())
for i in range(q):
line = input().split()
if line[0] == 'UPDATE':
# 更新操作,格式为UPDATE i val
index = int(line[1]) - 1
value = int(line[2])
tree.update_with_lazy(tree.tree, index, index, value)
else:
# 询问操作,格式为QUERY l r
left = int(line[1]) - 1
right = int(line[2]) - 1
print(tree.query(tree.tree, left, right))
以上是一个简单的解决方案,可用于解决 GATE CS 2021 设置1 问题16。