dynamic_fenwick_tree_multiset¶
ソースコード¶
from titan_pylib.data_structures.set.dynamic_fenwick_tree_multiset import DynamicFenwickTreeMultiset
展開済みコード¶
1# from titan_pylib.data_structures.set.dynamic_fenwick_tree_multiset import DynamicFenwickTreeMultiset
2# from titan_pylib.data_structures.set.dynamic_fenwick_tree_set import (
3# DynamicFenwickTreeSet,
4# )
5# from titan_pylib.data_structures.fenwick_tree.dynamic_fenwick_tree import (
6# DynamicFenwickTree,
7# )
8from typing import Optional, Final
9
10
11class DynamicFenwickTree:
12 """必要なところだけノードを作ります。"""
13
14 def __init__(self, u: int):
15 """Build DynamicFenwickTree [0, u)."""
16 assert isinstance(
17 u, int
18 ), f"TypeError: DynamicFenwickTree({u}), {u} must be int"
19 self._u: Final[int] = u
20 self._tree: dict[int, int] = {}
21 self._s: Final[int] = 1 << (u - 1).bit_length()
22
23 def add(self, k: int, x: int) -> None:
24 assert (
25 0 <= k < self._u
26 ), f"IndexError: DynamicFenwickTree.add({k}, {x}), u={self._u}"
27 k += 1
28 while k <= self._u:
29 if k in self._tree:
30 self._tree[k] += x
31 else:
32 self._tree[k] = x
33 k += k & -k
34
35 def pref(self, r: int) -> int:
36 assert (
37 0 <= r <= self._u
38 ), f"IndexError: DynamicFenwickTree.pref({r}), u={self._u}"
39 ret = 0
40 while r > 0:
41 ret += self._tree.get(r, 0)
42 r -= r & -r
43 return ret
44
45 def sum(self, l: int, r: int) -> int:
46 assert (
47 0 <= l <= r <= self._u
48 ), f"IndexError: DynamicFenwickTree.sum({l}, {r}), u={self._u}"
49 # return self.pref(r) - self.pref(l)
50 _tree = self._tree
51 res = 0
52 while r > l:
53 res += _tree.get(r, 0)
54 r -= r & -r
55 while l > r:
56 res -= _tree.get(l, 0)
57 l -= l & -l
58 return res
59
60 def bisect_left(self, w: int) -> Optional[int]:
61 i, s = 0, self._s
62 while s:
63 if i + s <= self._u:
64 if i + s in self._tree and self._tree[i + s] < w:
65 w -= self._tree[i + s]
66 i += s
67 elif i + s not in self._tree and 0 < w:
68 i += s
69 s >>= 1
70 return i if w else None
71
72 def bisect_right(self, w: int) -> int:
73 i, s = 0, self._s
74 while s:
75 if i + s <= self._u:
76 if i + s in self._tree and self._tree[i + s] <= w:
77 w -= self._tree[i + s]
78 i += s
79 elif i + s not in self._tree and 0 <= w:
80 i += s
81 s >>= 1
82 return i
83
84 def __str__(self):
85 return str(self._tree)
86from typing import Iterable, Optional
87
88
89class DynamicFenwickTreeSet:
90
91 # 整数[0, u)を、空間O(qlogu)/時間O(qlogu)
92
93 def __init__(self, u: int, a: Iterable[int] = []):
94 self._size: int = u
95 self._len: int = 0
96 self._cnt: dict[int, int] = {}
97 self._fw = DynamicFenwickTree(self._size)
98 for _a in a:
99 self.add(_a)
100
101 def add(self, key: int) -> bool:
102 if key in self._cnt:
103 return False
104 self._len += 1
105 self._cnt[key] = 1
106 self._fw.add(key, 1)
107 return True
108
109 def remove(self, key: int) -> None:
110 if self.discard(key):
111 return
112 raise KeyError(key)
113
114 def discard(self, key: int) -> bool:
115 if key in self._cnt:
116 self._len -= 1
117 del self._cnt[key]
118 self._fw.add(key, -1)
119 return True
120 return False
121
122 def le(self, key: int) -> Optional[int]:
123 if key in self._cnt:
124 return key
125 pref = self._fw.pref(key) - 1
126 return None if pref < 0 else self._fw.bisect_right(pref)
127
128 def lt(self, key: int) -> Optional[int]:
129 pref = self._fw.pref(key) - 1
130 return None if pref < 0 else self._fw.bisect_right(pref)
131
132 def ge(self, key: int) -> Optional[int]:
133 if key in self._cnt:
134 return key
135 pref = self._fw.pref(key + 1)
136 return None if pref >= self._len else self._fw.bisect_right(pref)
137
138 def gt(self, key: int) -> Optional[int]:
139 pref = self._fw.pref(key + 1)
140 return None if pref >= self._len else self._fw.bisect_right(pref)
141
142 def index(self, key: int) -> int:
143 return self._fw.pref(key)
144
145 def index_right(self, key: int) -> int:
146 return self._fw.pref(key + 1)
147
148 def pop(self, k: int = -1) -> int:
149 x = self.__getitem__(k)
150 self.discard(x)
151 return x
152
153 def pop_max(self) -> int:
154 assert self, "IndexError: pop_max() from empty DynamicFenwickTreeSet."
155 return self.pop()
156
157 def pop_min(self) -> int:
158 assert self, "IndexError: pop_min() from empty DynamicFenwickTreeSet."
159 return self.pop(0)
160
161 def __getitem__(self, k: int) -> int:
162 if k < 0:
163 k += self._len
164 return self._fw.bisect_right(k)
165
166 def __iter__(self):
167 self._iter = 0
168 return self
169
170 def __next__(self):
171 if self._iter == self._len:
172 raise StopIteration
173 res = self.__getitem__(self._iter)
174 self._iter += 1
175 return res
176
177 def __reversed__(self):
178 for i in range(self._len):
179 yield self.__getitem__(-i - 1)
180
181 def __len__(self):
182 return self._len
183
184 def __contains__(self, key: int):
185 return key in self._cnt
186
187 def __bool__(self):
188 return self._len > 0
189
190 def __str__(self):
191 return "{" + ", ".join(map(str, self)) + "}"
192
193 def __repr__(self):
194 return f"DynamicFenwickTreeSet({self})"
195from typing import Iterable
196
197
198class DynamicFenwickTreeMultiset(DynamicFenwickTreeSet):
199
200 def __init__(self, n: int, a: Iterable[int] = []) -> None:
201 super().__init__(n, a)
202
203 def add(self, key: int, val: int = 1) -> None:
204 self._len += val
205 if key in self._cnt:
206 self._cnt[key] += val
207 else:
208 self._cnt[key] = val
209 self._fw.add(key, val)
210
211 def discard(self, key: int, val: int = 1) -> bool:
212 if key not in self._cnt:
213 return False
214 cnt = self._cnt[key]
215 if val >= cnt:
216 self._len -= cnt
217 del self._cnt[key]
218 self._fw.add(key, -cnt)
219 else:
220 self._len -= val
221 self._cnt[key] -= val
222 self._fw.add(key, -val)
223 return True
224
225 def discard_all(self, key: int) -> bool:
226 return self.discard(key, val=self.count(key))
227
228 def count(self, key: int) -> int:
229 return self._cnt[key]
230
231 def items(self) -> Iterable[tuple[int, int]]:
232 _iter = 0
233 while _iter < self._len:
234 res = self.__getitem__(_iter)
235 cnt = self.count(res)
236 _iter += cnt
237 yield res, cnt
238
239 def show(self) -> None:
240 print("{" + ", ".join(f"{i[0]}: {i[1]}" for i in self.items()) + "}")
241
242 def __repr__(self):
243 return f"DynamicFenwickTreeMultiset({self})"
仕様¶
- class DynamicFenwickTreeMultiset(n: int, a: Iterable[int] = [])[source]¶
Bases:
DynamicFenwickTreeSet