python刷題常用模板

淋雨一直走49發表於2024-07-28

#===================================== 素數篩 Begin =====================================#
MAXN = 1000
prime = []
isprime = [True] * (MAXN + 1)
def euler():
    isprime[1] = False
    for i in range(2, MAXN + 1):
        if isprime[i]: prime.append(i)
        for pr in prime:
            if i * pr > MAXN: continue
            isprime[i * pr] = False
            if i % pr == 0: break
euler()
#===================================== 素數篩 Test =====================================#
assert isprime[1] is False
assert isprime[59] is True
assert isprime[293] is True
print("Euler Prime test passed!")
#===================================== 素數篩 End =====================================#

#===================================== 並查集 Begin =====================================#
class DSU:
    def __init__(self, n):
        self.parent = [i for i in range(n)]

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def merge(self, x, y):
        u, v = self.find(x), self.find(y)
        self.parent[u] = v
    
    def same(self, x, y) -> bool:
        return self.find(x) == self.find(y)
#===================================== 並查集 Test =====================================#
dsu = DSU(100)
assert dsu.same(1, 75) is False
dsu.merge(1, 50)
dsu.merge(25, 75)
dsu.merge(50, 25)
assert dsu.same(1, 75) is True
print("DSU test passed!")
#===================================== 並查集 End =====================================#

#===================================== 線段樹 Begin =====================================#
class SegmentTree:
    def __init__(self, v):
        self.n = len(v)
        self.n4 = 4 * self.n
        self.tree = [0] * self.n4
        self.lazy = [0] * self.n4
        self.arr = v
        self.root = 1
        self.end = self.n
        self.__build(0, self.end - 1, self.root)
        self.arr = None

    def query(self, l, r):
        return self.__query(1, self.end, self.root, l + 1, r + 1)

    def add(self, l, r, val):
        self.__add(1, self.end, self.root, l + 1, r + 1, val)

    def __build(self, s, t, idx):
        if s == t:
            self.tree[idx] = self.arr[s]
        else:
            m = s + ((t - s) >> 1)
            self.__build(s, m, 2 * idx)
            self.__build(m + 1, t, 2 * idx + 1)
            self.__pushup(idx)

    def __add(self, s, t, idx, l, r, val):
        if l <= s and t <= r:
            self.lazy[idx] += val
            self.tree[idx] += (t - s + 1) * val
        else:
            m = s + ((t - s) >> 1)
            self.__pushdown(s, t, idx)
            if l <= m:
                self.__add(s, m, 2 * idx, l, r, val)
            if m < r:
                self.__add(m + 1, t, 2 * idx + 1, l, r, val)
            self.__pushup(idx)

    def __query(self, s, t, idx, l, r):
        if l <= s and t <= r:
            return self.tree[idx]
        m = s + ((t - s) >> 1)
        self.__pushdown(s, t, idx)
        sm = 0
        if l <= m:
            sm += self.__query(s, m, 2 * idx, l, r)
        if m < r:
            sm += self.__query(m + 1, t, 2 * idx + 1, l, r)
        return sm

    def __pushup(self, idx):
        self.tree[idx] = self.tree[idx * 2] + self.tree[idx * 2 + 1]

    def __pushdown(self, s, t, idx):
        m = s + ((t - s) >> 1)
        if self.lazy[idx] != 0:
            self.lazy[idx * 2] += self.lazy[idx]
            self.tree[idx * 2] += (m - s + 1) * self.lazy[idx]
            self.lazy[idx * 2 + 1] += self.lazy[idx]
            self.tree[idx * 2 + 1] += (t - m) * self.lazy[idx]
            self.lazy[idx] = 0
#===================================== 線段樹 Test =====================================#
arr = [1, -2, 3, -4, 5]
seg = SegmentTree(arr)
assert seg.query(0, 2) == 2
seg.add(1, 3, 2)    # arr = [1, 0, 5, -2, 5]
assert seg.query(0, 3) == 4
print("SegmentTree1 test passed!")
#===================================== 線段樹 End =====================================#


#===================================== 線段樹 (動態開點)Begin =====================================#
class Node:
    def __init__(self, l, r):
        self.left = None
        self.right = None
        self.l = l
        self.r = r
        self.mid = (l + r) >> 1
        self.v = 0
        self.add = 0

class SegmentTree2:
    def __init__(self):
        self.root = Node(1, int(1e9))

    def modify(self, l, r, v, node=None):
        if l > r:
            return
        if node is None:
            node = self.root
        if node.l >= l and node.r <= r:
            node.v = v
            node.add = v
            return
        self.pushdown(node)
        if l <= node.mid:
            self.modify(l, r, v, node.left)
        if r > node.mid:
            self.modify(l, r, v, node.right)
        self.pushup(node)

    def query(self, l, r, node=None):
        if l > r:
            return 0
        if node is None:
            node = self.root
        if node.l >= l and node.r <= r:
            return node.v
        self.pushdown(node)
        v = 0
        if l <= node.mid:
            v = max(v, self.query(l, r, node.left))
        if r > node.mid:
            v = max(v, self.query(l, r, node.right))
        return v

    def pushup(self, node):
        node.v = max(node.left.v, node.right.v)

    def pushdown(self, node):
        if node.left is None:
            node.left = Node(node.l, node.mid)
        if node.right is None:
            node.right = Node(node.mid + 1, node.r)
        if node.add:
            node.left.v = node.add
            node.right.v = node.add
            node.left.add = node.add
            node.right.add = node.add
            node.add = 0
#===================================== 線段樹 (動態開點)Test =====================================#
seg = SegmentTree2()
seg.modify(0, 5, 2)
assert seg.query(0, 5) == 2
seg.modify(3, 7, 4)
assert seg.query(5, 5) == 4
print("SegmentTree2 test passed!")
#===================================== 線段樹 (動態開點)End =====================================#




相關文章