lazy_splay_tree_array

ソースコード

from titan_pylib.data_structures.splay_tree.lazy_splay_tree_array import LazySplayTreeArrayData
from titan_pylib.data_structures.splay_tree.lazy_splay_tree_array import LazySplayTreeArray

view on github

展開済みコード

  1# from titan_pylib.data_structures.splay_tree.lazy_splay_tree_array import LazySplayTreeArray
  2from array import array
  3from typing import (
  4    Generic,
  5    TypeVar,
  6    Callable,
  7    Iterable,
  8    Optional,
  9    Union,
 10    Sequence,
 11)
 12
 13T = TypeVar("T")
 14F = TypeVar("F")
 15
 16
 17class LazySplayTreeArrayData(Generic[T, F]):
 18
 19    def __init__(
 20        self,
 21        op: Optional[Callable[[T, T], T]] = None,
 22        mapping: Optional[Callable[[F, T], T]] = None,
 23        composition: Optional[Callable[[F, F], F]] = None,
 24        e: T = None,
 25        id: F = None,
 26    ):
 27        self.op: Callable[[T, T], T] = (lambda s, t: e) if op is None else op
 28        self.mapping: Callable[[F, T], T] = (lambda f, s: e) if op is None else mapping
 29        self.composition: Callable[[F, F], F] = (
 30            (lambda f, g: id) if op is None else composition
 31        )
 32        self.e: T = e
 33        self.id: F = id
 34        self.keydata: list[T] = [e, e]
 35        self.lazy: list[F] = [id]
 36        self.arr: array[int] = array("I", bytes(16))
 37        # left:  arr[node<<2]
 38        # right: arr[node<<2|1]
 39        # size:  arr[node<<2|2]
 40        # rev:   arr[node<<2|3]
 41        self.end: int = 1
 42
 43    def reserve(self, n: int) -> None:
 44        if n <= 0:
 45            return
 46        self.keydata += [self.e] * (2 * n)
 47        self.lazy += [self.id] * n
 48        self.arr += array("I", bytes(16 * n))
 49
 50
 51class LazySplayTreeArray(Generic[T, F]):
 52
 53    def __init__(
 54        self,
 55        data: "LazySplayTreeArrayData[T, F]",
 56        n_or_a: Union[int, Iterable[T]] = 0,
 57        _root: int = 0,
 58    ) -> None:
 59        self.data = data
 60        self.root = _root
 61        if not n_or_a:
 62            return
 63        if isinstance(n_or_a, int):
 64            a = [data.e] * n_or_a
 65        elif not isinstance(n_or_a, Sequence):
 66            a = list(n_or_a)
 67        else:
 68            a = n_or_a
 69        if a:
 70            self._build(a)
 71
 72    def _build(self, a: Sequence[T]) -> None:
 73        def rec(l: int, r: int) -> int:
 74            mid = (l + r) >> 1
 75            if l != mid:
 76                arr[mid << 2] = rec(l, mid)
 77            if mid + 1 != r:
 78                arr[mid << 2 | 1] = rec(mid + 1, r)
 79            self._update(mid)
 80            return mid
 81
 82        n = len(a)
 83        keydata, arr = self.data.keydata, self.data.arr
 84        end = self.data.end
 85        self.data.reserve(n + end - len(keydata) // 2 + 1)
 86        self.data.end += n
 87        for i, e in enumerate(a):
 88            keydata[end + i << 1] = e
 89            keydata[end + i << 1 | 1] = e
 90        self.root = rec(end, n + end)
 91
 92    def _make_node(self, key: T) -> int:
 93        data = self.data
 94        if data.end >= len(data.arr) // 4:
 95            data.keydata.append(key)
 96            data.keydata.append(key)
 97            data.lazy.append(data.id)
 98            data.arr.append(0)
 99            data.arr.append(0)
100            data.arr.append(1)
101            data.arr.append(0)
102        else:
103            data.keydata[data.end << 1] = key
104            data.keydata[data.end << 1 | 1] = key
105        data.end += 1
106        return data.end - 1
107
108    def _propagate(self, node: int) -> None:
109        data = self.data
110        arr = data.arr
111        if arr[node << 2 | 3]:
112            arr[node << 2], arr[node << 2 | 1] = arr[node << 2 | 1], arr[node << 2]
113            arr[node << 2 | 3] = 0
114            arr[arr[node << 2] << 2 | 3] ^= 1
115            arr[arr[node << 2 | 1] << 2 | 3] ^= 1
116        nlazy = data.lazy[node]
117        if nlazy == data.id:
118            return
119        lnode, rnode = arr[node << 2], arr[node << 2 | 1]
120        keydata, lazy = data.keydata, data.lazy
121        lazy[node] = data.id
122        if lnode:
123            lazy[lnode] = data.composition(nlazy, lazy[lnode])
124            lnode <<= 1
125            keydata[lnode] = data.mapping(nlazy, keydata[lnode])
126            keydata[lnode | 1] = data.mapping(nlazy, keydata[lnode | 1])
127        if rnode:
128            lazy[rnode] = data.composition(nlazy, lazy[rnode])
129            rnode <<= 1
130            keydata[rnode] = data.mapping(nlazy, keydata[rnode])
131            keydata[rnode | 1] = data.mapping(nlazy, keydata[rnode | 1])
132
133    def _update_triple(self, x: int, y: int, z: int) -> None:
134        data = self.data
135        keydata, arr = data.keydata, data.arr
136        lx, rx = arr[x << 2], arr[x << 2 | 1]
137        ly, ry = arr[y << 2], arr[y << 2 | 1]
138        arr[z << 2 | 2] = arr[x << 2 | 2]
139        arr[x << 2 | 2] = 1 + arr[lx << 2 | 2] + arr[rx << 2 | 2]
140        arr[y << 2 | 2] = 1 + arr[ly << 2 | 2] + arr[ry << 2 | 2]
141        keydata[z << 1 | 1] = keydata[x << 1 | 1]
142        keydata[x << 1 | 1] = data.op(
143            data.op(keydata[lx << 1 | 1], keydata[x << 1]), keydata[rx << 1 | 1]
144        )
145        keydata[y << 1 | 1] = data.op(
146            data.op(keydata[ly << 1 | 1], keydata[y << 1]), keydata[ry << 1 | 1]
147        )
148
149    def _update_double(self, x: int, y: int) -> None:
150        data = self.data
151        keydata, arr = data.keydata, data.arr
152        lx, rx = arr[x << 2], arr[x << 2 | 1]
153        arr[y << 2 | 2] = arr[x << 2 | 2]
154        arr[x << 2 | 2] = 1 + arr[lx << 2 | 2] + arr[rx << 2 | 2]
155        keydata[y << 1 | 1] = keydata[x << 1 | 1]
156        keydata[x << 1 | 1] = data.op(
157            data.op(keydata[lx << 1 | 1], keydata[x << 1]), keydata[rx << 1 | 1]
158        )
159
160    def _update(self, node: int) -> None:
161        data = self.data
162        keydata, arr = data.keydata, data.arr
163        lnode, rnode = arr[node << 2], arr[node << 2 | 1]
164        arr[node << 2 | 2] = 1 + arr[lnode << 2 | 2] + arr[rnode << 2 | 2]
165        keydata[node << 1 | 1] = data.op(
166            data.op(keydata[lnode << 1 | 1], keydata[node << 1]),
167            keydata[rnode << 1 | 1],
168        )
169
170    def _splay(self, path: list[int], d: int) -> None:
171        arr = self.data.arr
172        g = d & 1
173        while len(path) > 1:
174            pnode = path.pop()
175            gnode = path.pop()
176            f = d >> 1 & 1
177            node = arr[pnode << 2 | g ^ 1]
178            nnode = (pnode if g == f else node) << 2 | f
179            arr[pnode << 2 | g ^ 1] = arr[node << 2 | g]
180            arr[node << 2 | g] = pnode
181            arr[gnode << 2 | f ^ 1] = arr[nnode]
182            arr[nnode] = gnode
183            self._update_triple(gnode, pnode, node)
184            if not path:
185                return
186            d >>= 2
187            g = d & 1
188            arr[path[-1] << 2 | g ^ 1] = node
189        pnode = path.pop()
190        node = arr[pnode << 2 | g ^ 1]
191        arr[pnode << 2 | g ^ 1] = arr[node << 2 | g]
192        arr[node << 2 | g] = pnode
193        self._update_double(pnode, node)
194
195    def _kth_elm_splay(self, node: int, k: int) -> int:
196        arr = self.data.arr
197        if k < 0:
198            k += arr[node << 2 | 2]
199        d = 0
200        path = []
201        while True:
202            self._propagate(node)
203            t = arr[arr[node << 2] << 2 | 2]
204            if t == k:
205                if path:
206                    self._splay(path, d)
207                return node
208            d = d << 1 | (t > k)
209            path.append(node)
210            node = arr[node << 2 | (t < k)]
211            if t < k:
212                k -= t + 1
213
214    def _left_splay(self, node: int) -> int:
215        if not node:
216            return 0
217        self._propagate(node)
218        arr = self.data.arr
219        if not arr[node << 2]:
220            return node
221        path = []
222        while arr[node << 2]:
223            path.append(node)
224            node = arr[node << 2]
225            self._propagate(node)
226        self._splay(path, (1 << len(path)) - 1)
227        return node
228
229    def _right_splay(self, node: int) -> int:
230        if not node:
231            return 0
232        self._propagate(node)
233        arr = self.data.arr
234        if not arr[node << 2 | 1]:
235            return node
236        path = []
237        while arr[node << 2 | 1]:
238            path.append(node)
239            node = arr[node << 2 | 1]
240            self._propagate(node)
241        self._splay(path, 0)
242        return node
243
244    def reserve(self, n: int) -> None:
245        self.data.reserve(n)
246
247    def merge(self, other: "LazySplayTreeArray[T, F]") -> None:
248        assert self.data is other.data
249        if not other.root:
250            return
251        if not self.root:
252            self.root = other.root
253            return
254        self.root = self._right_splay(self.root)
255        self.data.arr[self.root << 2 | 1] = other.root
256        self._update(self.root)
257
258    def split(
259        self, k: int
260    ) -> tuple["LazySplayTreeArray[T, F]", "LazySplayTreeArray[T, F]"]:
261        assert (
262            -len(self) < k <= len(self)
263        ), f"IndexError: LazySplayTreeArray.split({k}), len={len(self)}"
264        if k < 0:
265            k += len(self)
266        if k >= self.data.arr[self.root << 2 | 2]:
267            return self, LazySplayTreeArray(self.data, _root=0)
268        self.root = self._kth_elm_splay(self.root, k)
269        left = LazySplayTreeArray(self.data, _root=self.data.arr[self.root << 2])
270        self.data.arr[self.root << 2] = 0
271        self._update(self.root)
272        return left, self
273
274    def _internal_split(self, k: int) -> tuple[int, int]:
275        if k >= self.data.arr[self.root << 2 | 2]:
276            return self.root, 0
277        self.root = self._kth_elm_splay(self.root, k)
278        left = self.data.arr[self.root << 2]
279        self.data.arr[self.root << 2] = 0
280        self._update(self.root)
281        return left, self.root
282
283    def reverse(self, l: int, r: int) -> None:
284        assert (
285            0 <= l <= r <= len(self)
286        ), f"IndexError: LazySplayTreeArray.reverse({l}, {r}), len={len(self)}"
287        if l == r:
288            return
289        data = self.data
290        left, right = self._internal_split(r)
291        if l:
292            left = self._kth_elm_splay(left, l - 1)
293        data.arr[(data.arr[left << 2 | 1] if l else left) << 2 | 3] ^= 1
294        if right:
295            data.arr[right << 2] = left
296            self._update(right)
297        self.root = right if right else left
298
299    def all_reverse(self) -> None:
300        self.data.arr[self.root << 2 | 3] ^= 1
301
302    def apply(self, l: int, r: int, f: F) -> None:
303        assert (
304            0 <= l <= r <= len(self)
305        ), f"IndexError: LazySplayTreeArray.apply({l}, {r}), len={len(self)}"
306        data = self.data
307        left, right = self._internal_split(r)
308        keydata, lazy = data.keydata, data.lazy
309        if l:
310            left = self._kth_elm_splay(left, l - 1)
311        node = data.arr[left << 2 | 1] if l else left
312        keydata[node << 1] = data.mapping(f, keydata[node << 1])
313        keydata[node << 1 | 1] = data.mapping(f, keydata[node << 1 | 1])
314        lazy[node] = data.composition(f, lazy[node])
315        if l:
316            self._update(left)
317        if right:
318            data.arr[right << 2] = left
319            self._update(right)
320        self.root = right if right else left
321
322    def all_apply(self, f: F) -> None:
323        if not self.root:
324            return
325        data, node = self.data, self.root
326        data.keydata[node << 1] = data.mapping(f, data.keydata[node << 1])
327        data.keydata[node << 1 | 1] = data.mapping(f, data.keydata[node << 1 | 1])
328        data.lazy[node] = data.composition(f, data.lazy[node])
329
330    def prod(self, l: int, r: int) -> T:
331        assert (
332            0 <= l <= r <= len(self)
333        ), f"IndexError: LazySplayTreeArray.prod({l}, {r}), len={len(self)}"
334        data = self.data
335        left, right = self._internal_split(r)
336        if l:
337            left = self._kth_elm_splay(left, l - 1)
338        res = data.keydata[(data.arr[left << 2 | 1] if l else left) << 1 | 1]
339        if right:
340            data.arr[right << 2] = left
341            self._update(right)
342        self.root = right if right else left
343        return res
344
345    def all_prod(self) -> T:
346        return self.data.keydata[self.root << 1 | 1]
347
348    def insert(self, k: int, key: T) -> None:
349        assert (
350            -len(self) <= k <= len(self)
351        ), f"IndexError: LazySplayTreeArray.insert({k}, {key}), len={len(self)}"
352        if k < 0:
353            k += len(self)
354        data = self.data
355        node = self._make_node(key)
356        if not self.root:
357            self._update(node)
358            self.root = node
359            return
360        arr = data.arr
361        if k == data.arr[self.root << 2 | 2]:
362            arr[node << 2] = self._right_splay(self.root)
363        else:
364            node_ = self._kth_elm_splay(self.root, k)
365            if arr[node_ << 2]:
366                arr[node << 2] = arr[node_ << 2]
367                arr[node_ << 2] = 0
368                self._update(node_)
369            arr[node << 2 | 1] = node_
370        self._update(node)
371        self.root = node
372
373    def append(self, key: T) -> None:
374        data = self.data
375        node = self._right_splay(self.root)
376        self.root = self._make_node(key)
377        data.arr[self.root << 2] = node
378        self._update(self.root)
379
380    def appendleft(self, key: T) -> None:
381        node = self._left_splay(self.root)
382        self.root = self._make_node(key)
383        self.data.arr[self.root << 2 | 1] = node
384        self._update(self.root)
385
386    def pop(self, k: int = -1) -> T:
387        assert -len(self) <= k < len(self), f"IndexError: LazySplayTreeArray.pop({k})"
388        data = self.data
389        if k == -1:
390            node = self._right_splay(self.root)
391            self._propagate(node)
392            self.root = data.arr[node << 2]
393            return data.keydata[node << 1]
394        self.root = self._kth_elm_splay(self.root, k)
395        res = data.keydata[self.root << 1]
396        if not data.arr[self.root << 2]:
397            self.root = data.arr[self.root << 2 | 1]
398        elif not data.arr[self.root << 2 | 1]:
399            self.root = data.arr[self.root << 2]
400        else:
401            node = self._right_splay(data.arr[self.root << 2])
402            data.arr[node << 2 | 1] = data.arr[self.root << 2 | 1]
403            self.root = node
404            self._update(self.root)
405        return res
406
407    def popleft(self) -> T:
408        assert self, "IndexError: LazySplayTreeArray.popleft()"
409        node = self._left_splay(self.root)
410        self.root = self.data.arr[node << 2 | 1]
411        return self.data.keydata[node << 1]
412
413    def rotate(self, x: int) -> None:
414        # 「末尾をを削除し先頭に挿入」をx回
415        n = self.data.arr[self.root << 2 | 2]
416        l, self = self.split(n - (x % n))
417        self.merge(l)
418
419    def tolist(self) -> list[T]:
420        node = self.root
421        arr, keydata = self.data.arr, self.data.keydata
422        stack = []
423        res = []
424        while stack or node:
425            if node:
426                self._propagate(node)
427                stack.append(node)
428                node = arr[node << 2]
429            else:
430                node = stack.pop()
431                res.append(keydata[node << 1])
432                node = arr[node << 2 | 1]
433        return res
434
435    def clear(self) -> None:
436        self.root = 0
437
438    def __setitem__(self, k: int, key: T):
439        assert (
440            -len(self) <= k < len(self)
441        ), f"IndexError: LazySplayTreeArray.__setitem__({k})"
442        self.root = self._kth_elm_splay(self.root, k)
443        self.data.keydata[self.root << 1] = key
444        self._update(self.root)
445
446    def __getitem__(self, k: int) -> T:
447        assert (
448            -len(self) <= k < len(self)
449        ), f"IndexError: LazySplayTreeArray.__getitem__({k})"
450        self.root = self._kth_elm_splay(self.root, k)
451        return self.data.keydata[self.root << 1]
452
453    def __iter__(self):
454        self.__iter = 0
455        return self
456
457    def __next__(self):
458        if self.__iter == self.data.arr[self.root << 2 | 2]:
459            raise StopIteration
460        res = self[self.__iter]
461        self.__iter += 1
462        return res
463
464    def __reversed__(self):
465        for i in range(len(self)):
466            yield self[-i - 1]
467
468    def __len__(self):
469        return self.data.arr[self.root << 2 | 2]
470
471    def __str__(self):
472        return str(self.tolist())
473
474    def __bool__(self):
475        return self.root != 0
476
477    def __repr__(self):
478        return f"{self.__class__.__name__}({self})"

仕様

class LazySplayTreeArray(data: LazySplayTreeArrayData[T, F], n_or_a: int | Iterable[T] = 0, _root: int = 0)[source]

Bases: Generic[T, F]

all_apply(f: F) None[source]
all_prod() T[source]
all_reverse() None[source]
append(key: T) None[source]
appendleft(key: T) None[source]
apply(l: int, r: int, f: F) None[source]
clear() None[source]
insert(k: int, key: T) None[source]
merge(other: LazySplayTreeArray[T, F]) None[source]
pop(k: int = -1) T[source]
popleft() T[source]
prod(l: int, r: int) T[source]
reserve(n: int) None[source]
reverse(l: int, r: int) None[source]
rotate(x: int) None[source]
split(k: int) tuple[LazySplayTreeArray[T, F], LazySplayTreeArray[T, F]][source]
tolist() list[T][source]
class LazySplayTreeArrayData(op: Callable[[T, T], T] | None = None, mapping: Callable[[F, T], T] | None = None, composition: Callable[[F, F], F] | None = None, e: T = None, id: F = None)[source]

Bases: Generic[T, F]

reserve(n: int) None[source]