cp-library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub kobejean/cp-library

:warning: cp_library/ds/bucket_list_cls.py

Code

import cp_library.ds.__header__
from math import ceil, sqrt
from typing import Iterable, Iterator, MutableSequence
from cp_library.misc.typing import _T

# https://github.com/tatyam-prime/SortedSet/blob/main/BucketList.py
class BucketList(MutableSequence[_T]):
    BUCKET_RATIO = 16
    SPLIT_RATIO = 24
    
    def __init__(self, a: Iterable[_T] = []) -> None:
        a = list(a)
        n = self.size = len(a)
        num_bucket = int(ceil(sqrt(n / self.BUCKET_RATIO)))
        self.a = [a[n * i // num_bucket : n * (i + 1) // num_bucket] for i in range(num_bucket)]

    def __iter__(self) -> Iterator[_T]:
        for i in self.a:
            for j in i: yield j

    def __reversed__(self) -> Iterator[_T]:
        for i in reversed(self.a):
            for j in reversed(i): yield j
    
    def __eq__(self, other):
        if len(self) != len(other): return False
        for x, y in zip(self, other):
            if x != y: return False
        return True
    
    def __len__(self) -> int:
        return self.size
    
    def __repr__(self):
        return "BucketList" + str(self.a)
    
    def __str__(self):
        return str(list(self))

    def __contains__(self, x: _T):
        for y in self:
            if x == y: return True
        return False
    
    def _insert(self, a: list[_T], b: int, i: int, x: _T):
        a.insert(i, x)
        self.size += 1
        if len(a) > len(self.a) * self.SPLIT_RATIO:
            mid = len(a) >> 1
            self.a[b:b+1] = [a[:mid], a[mid:]]

    def insert(self, i: int, x: _T):
        if self.size == 0:
            if i != 0 and i != -1: raise IndexError
            self.a = [[x]]
            self.size = 1
            return
        if i < 0:
            for b, a in enumerate(reversed(self.a)):
                i += len(a)
                if i >= 0: return self._insert(a, len(self.a) + ~b, i, x)
        else:
            for b, a in enumerate(self.a):
                if i <= len(a): return self._insert(a, b, i, x)
                i -= len(a)

    def append(self, x: _T):
        a = self.a[-1]
        return self._insert(a, len(self.a) - 1, len(a), x)
    
    def extend(self, a: Iterable[_T]):
        for x in a: self.append(x)
    
    def __getitem__(self, i: int):
        if i < 0:
            for a in reversed(self.a):
                i += len(a)
                if i >= 0: return a[i]
        else:
            for a in self.a:
                if i < len(a): return a[i]
                i -= len(a)
        raise IndexError
    
    def __setitem__(self, i: int, x: _T):
        if i < 0:
            for a in reversed(self.a):
                i += len(a)
                if i >= 0: a[i] = x
        else:
            for a in self.a:
                if i < len(a): a[i] = x
                i -= len(a)
        raise IndexError
    
    def _pop(self, a: list[_T], b: int, i: int):
        ans = a.pop(i)
        self.size -= 1
        if not a: del self.a[b]
        return ans
    
    def pop(self, i: int = -1):
        if i < 0:
            for b, a in enumerate(reversed(self.a)):
                i += len(a)
                if i >= 0: return self._pop(a, ~b, i)
        else:
            for b, a in enumerate(self.a):
                if i < len(a): return self._pop(a, b, i)
                i -= len(a)
        raise IndexError
    __delitem__ = pop

    def count(self, x: _T):
        return sum(x == y for y in self)

    def index(self, x: _T):
        for i, y in enumerate(self):
            if x == y: return i
        raise ValueError
    
    def remove(self, x: _T):
        self.pop(self.index(x))

    def clear(self):
        self.a = []
        self.size = 0

    def reverse(self):
        self.a.reverse()
        for a in self.a: a.reverse()

    def copy(self):
        return BucketList(self)
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
             https://kobejean.github.io/cp-library               
'''
from math import ceil, sqrt
from typing import Iterable, Iterator, MutableSequence
from typing import TypeVar
_T = TypeVar('T')

# https://github.com/tatyam-prime/SortedSet/blob/main/BucketList.py
class BucketList(MutableSequence[_T]):
    BUCKET_RATIO = 16
    SPLIT_RATIO = 24
    
    def __init__(self, a: Iterable[_T] = []) -> None:
        a = list(a)
        n = self.size = len(a)
        num_bucket = int(ceil(sqrt(n / self.BUCKET_RATIO)))
        self.a = [a[n * i // num_bucket : n * (i + 1) // num_bucket] for i in range(num_bucket)]

    def __iter__(self) -> Iterator[_T]:
        for i in self.a:
            for j in i: yield j

    def __reversed__(self) -> Iterator[_T]:
        for i in reversed(self.a):
            for j in reversed(i): yield j
    
    def __eq__(self, other):
        if len(self) != len(other): return False
        for x, y in zip(self, other):
            if x != y: return False
        return True
    
    def __len__(self) -> int:
        return self.size
    
    def __repr__(self):
        return "BucketList" + str(self.a)
    
    def __str__(self):
        return str(list(self))

    def __contains__(self, x: _T):
        for y in self:
            if x == y: return True
        return False
    
    def _insert(self, a: list[_T], b: int, i: int, x: _T):
        a.insert(i, x)
        self.size += 1
        if len(a) > len(self.a) * self.SPLIT_RATIO:
            mid = len(a) >> 1
            self.a[b:b+1] = [a[:mid], a[mid:]]

    def insert(self, i: int, x: _T):
        if self.size == 0:
            if i != 0 and i != -1: raise IndexError
            self.a = [[x]]
            self.size = 1
            return
        if i < 0:
            for b, a in enumerate(reversed(self.a)):
                i += len(a)
                if i >= 0: return self._insert(a, len(self.a) + ~b, i, x)
        else:
            for b, a in enumerate(self.a):
                if i <= len(a): return self._insert(a, b, i, x)
                i -= len(a)

    def append(self, x: _T):
        a = self.a[-1]
        return self._insert(a, len(self.a) - 1, len(a), x)
    
    def extend(self, a: Iterable[_T]):
        for x in a: self.append(x)
    
    def __getitem__(self, i: int):
        if i < 0:
            for a in reversed(self.a):
                i += len(a)
                if i >= 0: return a[i]
        else:
            for a in self.a:
                if i < len(a): return a[i]
                i -= len(a)
        raise IndexError
    
    def __setitem__(self, i: int, x: _T):
        if i < 0:
            for a in reversed(self.a):
                i += len(a)
                if i >= 0: a[i] = x
        else:
            for a in self.a:
                if i < len(a): a[i] = x
                i -= len(a)
        raise IndexError
    
    def _pop(self, a: list[_T], b: int, i: int):
        ans = a.pop(i)
        self.size -= 1
        if not a: del self.a[b]
        return ans
    
    def pop(self, i: int = -1):
        if i < 0:
            for b, a in enumerate(reversed(self.a)):
                i += len(a)
                if i >= 0: return self._pop(a, ~b, i)
        else:
            for b, a in enumerate(self.a):
                if i < len(a): return self._pop(a, b, i)
                i -= len(a)
        raise IndexError
    __delitem__ = pop

    def count(self, x: _T):
        return sum(x == y for y in self)

    def index(self, x: _T):
        for i, y in enumerate(self):
            if x == y: return i
        raise ValueError
    
    def remove(self, x: _T):
        self.pop(self.index(x))

    def clear(self):
        self.a = []
        self.size = 0

    def reverse(self):
        self.a.reverse()
        for a in self.a: a.reverse()

    def copy(self):
        return BucketList(self)
Back to top page