- Identify the ordered answer range or sorted search domain.
- Write a predicate whose truth changes only once.
- Move the appropriate boundary after each midpoint check and return the final feasible position.
Code notes
- 226 lines of Python from the credited upstream file abc217_d.py.
- The implementation visibly relies on sequence storage, ordered lookup.
- No explicit loop blocks detected.
Complexity
Multiply the logarithmic number of midpoint checks by the cost of one predicate evaluation.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
12 3class BalancingTree:4 """5 Self-balancing binary search tree using pivot values.6 7 See:8 https:qiita.com/Kiri8128/items/6256f8559f0026485d909 """10 11 def __init__(self, n):12 self.N = n13 self.root = self.node(1 << n, 1 << n)14 15 def append(self, v): 16 v += 117 nd = self.root18 19 while True:20 if v == nd.value:21 22 23 return 024 else:25 mi, ma = min(v, nd.value), max(v, nd.value)26 27 if mi < nd.pivot:28 nd.value = ma29 30 if nd.left:31 nd = nd.left32 v = mi33 else:34 p = nd.pivot35 nd.left = self.node(mi, p - (p & -p) 2)36 break37 else:38 nd.value = mi39 40 if nd.right:41 nd = nd.right42 v = ma43 else:44 p = nd.pivot45 nd.right = self.node(ma, p + (p & -p) 2)46 break47 48 def leftmost(self, nd):49 if nd.left: 50 return self.leftmost(nd.left)51 return nd52 53 def rightmost(self, nd):54 if nd.right: 55 return self.rightmost(nd.right)56 return nd57 58 def find_l(self, v):59 """The maximum value among the values truly less than v (If not, -1).60 """61 62 v += 163 nd = self.root64 prev = 065 66 if nd.value < v: 67 prev = nd.value68 69 while True:70 if v <= nd.value:71 if nd.left:72 nd = nd.left73 else:74 return prev - 175 else:76 prev = nd.value77 78 if nd.right:79 nd = nd.right80 else:81 return prev - 182 83 def find_r(self, v):84 """The smallest value among the values truly greater than v 85 (if not, root).86 """87 88 v += 189 nd = self.root90 prev = 091 92 if nd.value > v: 93 prev = nd.value94 95 while True:96 if v < nd.value:97 prev = nd.value98 99 if nd.left:100 nd = nd.left101 else:102 return prev - 1103 else:104 if nd.right:105 nd = nd.right106 else:107 return prev - 1108 109 @property110 def max(self):111 return self.find_l((1 << self.N) - 1)112 113 @property114 def min(self):115 return self.find_r(-1)116 117 def delete(self, v, nd = None, prev = None):118 v += 1119 120 if not nd: 121 nd = self.root122 if not prev: 123 prev = nd124 125 while v != nd.value:126 prev = nd127 128 if v <= nd.value:129 if nd.left:130 nd = nd.left131 else:132 133 return134 else:135 if nd.right:136 nd = nd.right137 else:138 139 return140 141 if (not nd.left) and (not nd.right):142 if not prev.left:143 prev.right = None144 elif not prev.right:145 prev.left = None146 else:147 if nd.pivot == prev.left.pivot:148 prev.left = None149 else:150 prev.right = None151 152 elif nd.right:153 154 nd.value = self.leftmost(nd.right).value155 self.delete(nd.value - 1, nd.right, nd) 156 else:157 158 nd.value = self.rightmost(nd.left).value159 self.delete(nd.value - 1, nd.left, nd)160 161 def __contains__(self, v: int) -> bool:162 return self.find_r(v - 1) == v163 164 class node:165 def __init__(self, v, p):166 self.value = v167 self.pivot = p168 self.left = None169 self.right = None170 171 def debug(self):172 def debug_info(nd_):173 return (nd_.value - 1, nd_.pivot - 1, nd_.left.value - 1 if nd_.left else -1, nd_.right.value - 1 if nd_.right else -1)174 175 def debug_node(nd):176 re = []177 178 if nd.left:179 re += debug_node(nd.left)180 if nd.value: 181 re.append(debug_info(nd))182 if nd.right:183 re += debug_node(nd.right)184 return re185 186 print("Debug - root =", self.root.value - 1, debug_node(self.root)[:50])187 188 def debug_list(self):189 def debug_node(nd):190 re = []191 192 if nd.left:193 re += debug_node(nd.left)194 if nd.value: 195 re.append(nd.value - 1)196 if nd.right:197 re += debug_node(nd.right)198 return re199 return debug_node(self.root)[:-1]200 201 202def main():203 import sys204 205 input = sys.stdin.readline206 207 l, q = map(int, input().split())208 bt = BalancingTree(31) 209 bt.append(0)210 bt.append(l)211 212 for _ in range(q):213 ci, qi = map(int, input().split())214 215 if ci == 1:216 bt.append(qi)217 else:218 left = bt.find_l(qi)219 right = bt.find_r(qi)220 221 print(right - left)222 223 224if __name__ == "__main__":225 main()226