Source code for titan_pylib.graph.hld.hld_segment_tree
1from titan_pylib.data_structures.segment_tree.segment_tree import SegmentTree
2from titan_pylib.graph.hld.hld import HLD
3from typing import Union, Iterable, Callable, TypeVar, Generic
4
5T = TypeVar("T")
6
7
[docs]
8class HLDSegmentTree(Generic[T]):
9 """セグ木搭載HLDです。
10
11 Note:
12 **非可換に対応していません。**
13 """
14
15 def __init__(
16 self, hld: HLD, n_or_a: Union[int, Iterable[T]], op: Callable[[T, T], T], e: T
17 ) -> None:
18 self.hld: HLD = hld
19 n_or_a = (
20 n_or_a if isinstance(n_or_a, int) else self.hld.build_list(list(n_or_a))
21 )
22 self.seg: SegmentTree[T] = SegmentTree(n_or_a, op, e)
23 self.op: Callable[[T, T], T] = op
24 self.e: T = e
25
[docs]
26 def path_prod(self, u: int, v: int) -> T:
27 """頂点 ``u`` から頂点 ``v`` へのパスの集約値を返します。
28 :math:`O(\\log^2{n})` です。
29
30 Note:
31 **非可換に対応していません。**
32
33 Args:
34 u (int): パスの端点です。
35 v (int): パスの端点です。
36
37 Returns:
38 T: 求める集約値です。
39 """
40 head, nodein, dep, par = (
41 self.hld.head,
42 self.hld.nodein,
43 self.hld.dep,
44 self.hld.par,
45 )
46 res = self.e
47 while head[u] != head[v]:
48 if dep[head[u]] < dep[head[v]]:
49 u, v = v, u
50 res = self.op(res, self.seg.prod(nodein[head[u]], nodein[u] + 1))
51 u = par[head[u]]
52 if dep[u] < dep[v]:
53 u, v = v, u
54 return self.op(res, self.seg.prod(nodein[v], nodein[u] + 1))
55
[docs]
56 def get(self, k: int) -> T:
57 """頂点の値を返します。
58 :math:`O(\\log{n})` です。
59
60 Args:
61 k (int): 頂点のインデックスです。
62
63 Returns:
64 T: 頂点の値です。
65 """
66 return self.seg[self.hld.nodein[k]]
67
[docs]
68 def set(self, k: int, v: T) -> None:
69 """頂点の値を更新します。
70 :math:`O(\\log{n})` です。
71
72 Args:
73 k (int): 頂点のインデックスです。
74 v (T): 更新する値です。
75 """
76 self.seg[self.hld.nodein[k]] = v
77
78 __getitem__ = get
79 __setitem__ = set
80
[docs]
81 def subtree_prod(self, v: int) -> T:
82 """部分木の集約値を返します。
83 :math:`O(\\log{n})` です。
84
85 Args:
86 v (int): 根とする頂点です。
87
88 Returns:
89 T: 求める集約値です。
90 """
91 return self.seg.prod(self.hld.nodein[v], self.hld.nodeout[v])