📜  门| GATE CS 2021 |设置1 |问题16(1)

📅  最后修改于: 2023-12-03 14:58:22.150000             🧑  作者: Mango

门 | GATE CS 2021 | 设置1 | 问题16

这是 GATE CS 2021 设置1 问题16 的介绍,它实际上是一道编程题。

题目描述

给定一个包含 n 个正整数的列表,您需要实现以下操作:

  1. UPDATE i val:将列表中索引 i 处的数更新为 val
  2. QUERY l r:询问列表中 [l, r] 区间内的数之和。

在给定的列表上执行多个操作,您需要输出每个查询操作的答案。

输入格式

输入的第一行包含一个整数 n,表示列表中元素个数。

接下来的一行包含 n 个整数,表示列表中的元素。

接下来的一行包含一个整数 q,表示要执行的操作次数。

接下来的 q 行描述每次操作,每次操作可能是以下两种之一:

  1. UPDATE i val:表示对索引 i 执行更新操作,将其值设置为 val(1 <= i <= n,1 <= val <= 10^9)。
  2. 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。