Source code for titan_pylib.data_structures.static_array_query.static_RmQ

 1from typing import Iterable
 2from array import array
 3
 4
[docs] 5class StaticRmQ: 6
[docs] 7 class SparseTableRmQ: 8 9 def __init__(self, a: list[int], INF: int): 10 size = len(a) 11 log = size.bit_length() - 1 12 data = [a] + [[]] * log 13 for i in range(log): 14 pre = data[i] 15 l = 1 << i 16 data[i + 1] = [min(pre[j], pre[j + l]) for j in range(len(pre) - l)] 17 self.size = size 18 self.data = data 19 self.INF = INF 20
[docs] 21 def prod(self, l: int, r: int) -> int: 22 if l >= r: 23 return self.INF 24 u = (r - l).bit_length() - 1 25 return min(self.data[u][l], self.data[u][r - (1 << u)])
26 27 def __init__(self, a: Iterable[int], INF=10**9): 28 a = list(a) 29 n = len(a) 30 bucket_size = n.bit_length() // 2 + 1 31 bucket_size = 31 32 bucket_cnt = (n + bucket_size - 1) // bucket_size 33 bucket = [a[bucket_size * i : bucket_size * (i + 1)] for i in range(bucket_cnt)] 34 bucket_data = StaticRmQ.SparseTableRmQ([min(b) for b in bucket], INF) 35 bucket_bit = array("I", bytes(4 * bucket_size * bucket_cnt)) 36 37 for i, b in enumerate(bucket): 38 stack = [] 39 for j, e in enumerate(b): 40 g = -1 41 while stack and b[stack[-1]] > e: 42 stack.pop() 43 if stack: 44 g = stack[-1] 45 stack.append(j) 46 if g == -1: 47 continue 48 bucket_bit[i * bucket_size + j] = bucket_bit[i * bucket_size + g] | ( 49 1 << g 50 ) 51 self.n = n 52 self.INF = INF 53 self.bucket_size = bucket_size 54 self.bucket_data = bucket_data 55 self.bucket = bucket 56 self.bucket_bit = bucket_bit 57
[docs] 58 def prod(self, l: int, r: int) -> int: 59 assert ( 60 0 <= l <= r <= self.n 61 ), f"IndexError: {self.__class__.__name__}.prod({l}, {r}), n={self.n}" 62 if l == r: 63 return self.INF 64 k1 = l // self.bucket_size 65 k2 = r // self.bucket_size 66 l -= k1 * self.bucket_size 67 r -= k2 * self.bucket_size + 1 68 if k1 == k2: 69 bit = self.bucket_bit[k1 * self.bucket_size + r] >> l 70 return self.bucket[k1][(bit & (-bit)).bit_length() + l - 1 if bit else r] 71 ans = self.INF 72 if l < len(self.bucket[k1]): 73 bit = self.bucket_bit[k1 * self.bucket_size + len(self.bucket[k1]) - 1] >> l 74 ans = self.bucket[k1][(bit & (-bit)).bit_length() + l - 1 if bit else -1] 75 ans = min(ans, self.bucket_data.prod(k1 + 1, k2)) 76 if r >= 0: 77 bit = self.bucket_bit[k2 * self.bucket_size + r] 78 ans = min( 79 ans, self.bucket[k2][(bit & (-bit)).bit_length() - 1 if bit else r] 80 ) 81 return ans