📜  资质 |门 CS 1998 |第 70 题(1)

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

资质 |门 CS 1998 |第 70 题

题目描述

给定一个长度为n的非负整数序列,如何快速求出一个区间的所有数的和。

思路分析
暴力解法

最简单的方法是对于每个查询操作,对区间内的所有数求和,时间复杂度为O(qn),其中q为查询的次数,n为序列长度。

前缀和

由于查询操作涉及到连续的区间和,因此可以事先计算出所有前缀和,即sum[i]表示前i个数的和,然后对于每个查询操作,只需计算sum[r]-sum[l-1]即可得到区间[l,r]内数的和。时间复杂度为O(n+q)。

线段树

线段树是一种经典的数据结构,具有良好的时间复杂度和空间复杂度。可以用线段树来维护整个序列,对于每个节点维护其表示的区间和。查询操作时,对于区间[l,r],可以在O(log n)的时间内找到其在线段树上的对应节点,然后返回其区间和。时间复杂度为O(nlogn+qlogn)。

代码实现
前缀和
def prefix_sum(nums):
    n = len(nums)
    sum = [0] * n
    sum[0] = nums[0]
    for i in range(1,n):
        sum[i] = sum[i-1] + nums[i]
    return sum

def sum_between(sum,l,r):
    if l == 0:
        return sum[r]
    else:
        return sum[r] - sum[l-1]
线段树
class SegTree:
    def __init__(self, nums):
        self.n = len(nums)
        self.tree = [0] * (4 * self.n)
        self.build(nums, 1, 0, self.n-1)

    def build(self, nums, i, l, r):
        if l == r:
            self.tree[i] = nums[l]
        else:
            m = (l + r) // 2
            self.build(nums, 2*i, l, m)
            self.build(nums, 2*i+1, m+1, r)
            self.tree[i] = self.tree[2*i] + self.tree[2*i+1]

    def query(self, i, ql, qr, l, r):
        if ql <= l and qr >= r:
            return self.tree[i]
        elif ql > r or qr < l:
            return 0
        else:
            m = (l + r) // 2
            return self.query(2*i, ql, qr, l, m) + self.query(2*i+1, ql, qr, m+1, r)

以上代码仅是示例,具体实现细节还需根据不同情况进行调整。