Source code for titan_pylib.data_structures.array.partial_persistent_array
1from typing import Iterable, TypeVar, Generic
2
3T = TypeVar("T")
4
5
[docs]
6class PartialPersistentArray(Generic[T]):
7 """部分永続配列です。
8 最新版の更新と、過去へのアクセスが可能です。
9 """
10
11 def __init__(self, a: Iterable[T]):
12 """``a`` から部分永続配列を構築します。
13 初期配列のバージョンは ``0`` です。
14 :math:`O(n)` です。
15 """
16 self.a: list[list[T]] = [[e] for e in a]
17 self.t: list[list[int]] = [[0] for _ in range(len(self.a))]
18 self.last_time: int = 0
19
[docs]
20 def set(self, k: int, v: T, t: int) -> None:
21 """位置 ``k`` を ``v`` に更新します。
22 :math:`O(1)` です。
23
24 Args:
25 k (int): インデックスです。
26 v (T): 更新する値です。
27 t (int): 新たな配列のバージョンです。
28 """
29 assert t >= self.last_time
30 assert t > self.t[k][-1]
31 self.a[k].append(v)
32 self.t[k].append(t)
33 self.last_time = t
34
[docs]
35 def get(self, k: int, t: int = -1) -> T:
36 """位置 ``k`` 、バージョン ``t`` の要素を返します。
37 :math:`O(\\log{n})` です。
38
39 Args:
40 k (int): インデックスです。
41 t (int, optional): バージョンです。デフォルトは最新バージョンです。
42 """
43 if t == -1 or t >= self.t[k][-1]:
44 return self.a[k][-1]
45 tk = self.t[k]
46 ok, ng = 0, len(tk)
47 while ng - ok > 1:
48 mid = (ok + ng) // 2
49 if tk[mid] <= t:
50 ok = mid
51 else:
52 ng = mid
53 return self.a[k][ok]
54
[docs]
55 def tolist(self, t: int) -> list[T]:
56 """バージョン ``t`` の配列を返します。
57 :math:`O(n\\log{n})` です。
58 """
59 return [self.get(i, t) for i in range(len(self))]
60
[docs]
61 def show(self, t: int) -> None:
62 print(f"Time: {t}", end="")
63 print([self.get(i, t) for i in range(len(self))])
64
[docs]
65 def show_all(self) -> None:
66 """すべてのバージョンの配列を表示します。"""
67 for i in range(self.last_time):
68 self.show(i)
69
70 def __len__(self):
71 return len(self.a)