线段树“卡常”求助

P3372 【模板】线段树 1

escapist404 @ 2023-07-24 21:56:19

class SegmentTree:
    val = []
    tag = []
    child = []
    root = 0
    size = 0

    def __new_node(self):
        self.val.append(0)
        self.tag.append(0)
        self.child.append([0, 0])
        return len(self.val) - 1

    def __push_down(self, index:int, size:int):
        if self.child[index][0] == 0:
            self.child[index][0] = self.__new_node()
        if self.child[index][1] == 0:
            self.child[index][1] = self.__new_node()
        self.val[self.child[index][0]] = self.apply(self.val[self.child[index][0]], self.tag[index], int(size / 2))
        self.val[self.child[index][1]] = self.apply(self.val[self.child[index][1]], self.tag[index], size - int(size / 2))
        self.tag[self.child[index][0]] = self.attach(self.tag[self.child[index][0]], self.tag[index])
        self.tag[self.child[index][1]] = self.attach(self.tag[self.child[index][1]], self.tag[index])
        self.tag[index] = self.e_tag()

    def __push_up(self, index):
        self.val[index] = self.opt(self.val[self.child[index][0]], self.val[self.child[index][1]])

    def __set(self, _l:int, _r:int, _tag, l:int, r:int, index:int):
        if l >= _r or r <= _l:
            return
        if _l <= l and r <= _r:
            self.val[index] = self.apply(self.val[index], _tag, r - l)
            self.tag[index] = self.attach(self.tag[index], _tag)
            return
        self.__push_down(index, r - l)
        mid = int((l + r) / 2)
        self.__set(_l, _r, _tag, l, mid, self.child[index][0])
        self.__set(_l, _r, _tag, mid, r, self.child[index][1])
        self.__push_up(index)

    def __get(self, _l:int, _r:int, l:int, r:int, index:int):
        if l >= _r or r <= _l:
            return self.e_val()
        if _l <= l and r <= _r:
            return self.val[index]
        self.__push_down(index, r - l)
        mid = int((l + r) / 2)
        if _l >= mid:
            return self.__get(_l, _r, mid, r, self.child[index][1])
        if _r <= mid:
            return self.__get(_l, _r, l, mid, self.child[index][0])
        return self.opt(self.__get(_l, _r, l, mid, self.child[index][0]), self.__get(_l, _r, mid, r, self.child[index][1]))

    def setRange(self, _l:int, _r:int, _tag):
        self.__set(_l, _r, _tag, 0, self.size, self.root)

    def setPos(self, _pos:int, _tag):
        self.__set(_pos, _pos + 1, _tag, 0, self.size, self.root)

    def getRange(self, _l:int, _r:int):
        return self.__get(_l, _r, 0, self.size, self.root)

    def getPos(self, _pos:int):
        return self.__get(_pos, _pos + 1, 0, self.size, self.root)

    def getAll(self):
        return self.val[self.root]

    def __init__(self, n:int, opt, e_val, apply, attach, e_tag):
        self.root = self.__new_node()
        self.size = n
        self.opt = opt
        self.e_val = e_val
        self.apply = apply
        self.attach = attach
        self.e_tag = e_tag

n, m = [int(i) for i in input().split()]

T = SegmentTree(n, lambda ls, rs : ls + rs, lambda : 0, lambda _val, _tag, _size : _val + _tag * _size, lambda _tag_old, _tag_new : _tag_old + _tag_new, lambda : 0)

a = [int(i) for i in input().split()]

for i in range(n):
    T.setPos(i, a[i])

for i in range(m):
    opt = [int(i) for i in input().split()]
    if opt[0] == 1:
        T.setRange(opt[1] - 1, opt[2], opt[3])
    else:
        print(T.getRange(opt[1] - 1, opt[2]))

如题,使用 python 实现了一棵线段树,但无法通过本题(#7~#10 TLE)。

初步原因猜测是 python 本身常数大,导致理论复杂度正确而无法通过。

因此求助针对这份代码的优化。doge


by fjy666 @ 2023-07-24 21:58:48

选 PyPy3


|