Source code for titan_pylib.data_structures.set.dynamic_fenwick_tree_set

  1from titan_pylib.data_structures.fenwick_tree.dynamic_fenwick_tree import (
  2    DynamicFenwickTree,
  3)
  4from typing import Iterable, Optional
  5
  6
[docs] 7class DynamicFenwickTreeSet: 8 9 # 整数[0, u)を、空間O(qlogu)/時間O(qlogu) 10 11 def __init__(self, u: int, a: Iterable[int] = []): 12 self._size: int = u 13 self._len: int = 0 14 self._cnt: dict[int, int] = {} 15 self._fw = DynamicFenwickTree(self._size) 16 for _a in a: 17 self.add(_a) 18
[docs] 19 def add(self, key: int) -> bool: 20 if key in self._cnt: 21 return False 22 self._len += 1 23 self._cnt[key] = 1 24 self._fw.add(key, 1) 25 return True
26
[docs] 27 def remove(self, key: int) -> None: 28 if self.discard(key): 29 return 30 raise KeyError(key)
31
[docs] 32 def discard(self, key: int) -> bool: 33 if key in self._cnt: 34 self._len -= 1 35 del self._cnt[key] 36 self._fw.add(key, -1) 37 return True 38 return False
39
[docs] 40 def le(self, key: int) -> Optional[int]: 41 if key in self._cnt: 42 return key 43 pref = self._fw.pref(key) - 1 44 return None if pref < 0 else self._fw.bisect_right(pref)
45
[docs] 46 def lt(self, key: int) -> Optional[int]: 47 pref = self._fw.pref(key) - 1 48 return None if pref < 0 else self._fw.bisect_right(pref)
49
[docs] 50 def ge(self, key: int) -> Optional[int]: 51 if key in self._cnt: 52 return key 53 pref = self._fw.pref(key + 1) 54 return None if pref >= self._len else self._fw.bisect_right(pref)
55
[docs] 56 def gt(self, key: int) -> Optional[int]: 57 pref = self._fw.pref(key + 1) 58 return None if pref >= self._len else self._fw.bisect_right(pref)
59
[docs] 60 def index(self, key: int) -> int: 61 return self._fw.pref(key)
62
[docs] 63 def index_right(self, key: int) -> int: 64 return self._fw.pref(key + 1)
65
[docs] 66 def pop(self, k: int = -1) -> int: 67 x = self.__getitem__(k) 68 self.discard(x) 69 return x
70
[docs] 71 def pop_max(self) -> int: 72 assert self, "IndexError: pop_max() from empty DynamicFenwickTreeSet." 73 return self.pop()
74
[docs] 75 def pop_min(self) -> int: 76 assert self, "IndexError: pop_min() from empty DynamicFenwickTreeSet." 77 return self.pop(0)
78 79 def __getitem__(self, k: int) -> int: 80 if k < 0: 81 k += self._len 82 return self._fw.bisect_right(k) 83 84 def __iter__(self): 85 self._iter = 0 86 return self 87 88 def __next__(self): 89 if self._iter == self._len: 90 raise StopIteration 91 res = self.__getitem__(self._iter) 92 self._iter += 1 93 return res 94 95 def __reversed__(self): 96 for i in range(self._len): 97 yield self.__getitem__(-i - 1) 98 99 def __len__(self): 100 return self._len 101 102 def __contains__(self, key: int): 103 return key in self._cnt 104 105 def __bool__(self): 106 return self._len > 0 107 108 def __str__(self): 109 return "{" + ", ".join(map(str, self)) + "}" 110 111 def __repr__(self): 112 return f"DynamicFenwickTreeSet({self})"