- 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
- 243 lines of Python from the credited upstream file abc228_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 3 4class BalancingTree:5 """6 Self-balancing binary search tree using pivot values.7 `std::set` in C++.8 See:9 https:qiita.com/Kiri8128/items/6256f8559f0026485d9010 """11 12 def __init__(self, n):13 self.N = n14 self.root = self.node(1 << n, 1 << n)15 16 def append(self, v): 17 v += 118 nd = self.root19 20 while True:21 if v == nd.value:22 23 24 return 025 else:26 mi, ma = min(v, nd.value), max(v, nd.value)27 28 if mi < nd.pivot:29 nd.value = ma30 31 if nd.left:32 nd = nd.left33 v = mi34 else:35 p = nd.pivot36 nd.left = self.node(mi, p - (p & -p) 2)37 break38 else:39 nd.value = mi40 41 if nd.right:42 nd = nd.right43 v = ma44 else:45 p = nd.pivot46 nd.right = self.node(ma, p + (p & -p) 2)47 break48 49 def leftmost(self, nd):50 if nd.left: 51 return self.leftmost(nd.left)52 return nd53 54 def rightmost(self, nd):55 if nd.right: 56 return self.rightmost(nd.right)57 return nd58 59 def find_l(self, v):60 """The maximum value among the values truly less than v (If not, -1).61 """62 63 v += 164 nd = self.root65 prev = 066 67 if nd.value < v: 68 prev = nd.value69 70 while True:71 if v <= nd.value:72 if nd.left:73 nd = nd.left74 else:75 return prev - 176 else:77 prev = nd.value78 79 if nd.right:80 nd = nd.right81 else:82 return prev - 183 84 def find_r(self, v):85 """The smallest value among the values truly greater than v 86 (if not, root).87 """88 89 v += 190 nd = self.root91 prev = 092 93 if nd.value > v: 94 prev = nd.value95 96 while True:97 if v < nd.value:98 prev = nd.value99 100 if nd.left:101 nd = nd.left102 else:103 return prev - 1104 else:105 if nd.right:106 nd = nd.right107 else:108 return prev - 1109 110 @property111 def max(self):112 return self.find_l((1 << self.N) - 1)113 114 @property115 def min(self):116 return self.find_r(-1)117 118 def delete(self, v, nd = None, prev = None):119 v += 1120 121 if not nd: 122 nd = self.root123 if not prev: 124 prev = nd125 126 while v != nd.value:127 prev = nd128 129 if v <= nd.value:130 if nd.left:131 nd = nd.left132 else:133 134 return135 else:136 if nd.right:137 nd = nd.right138 else:139 140 return141 142 if (not nd.left) and (not nd.right):143 if not prev.left:144 prev.right = None145 elif not prev.right:146 prev.left = None147 else:148 if nd.pivot == prev.left.pivot:149 prev.left = None150 else:151 prev.right = None152 153 elif nd.right:154 155 nd.value = self.leftmost(nd.right).value156 self.delete(nd.value - 1, nd.right, nd) 157 else:158 159 nd.value = self.rightmost(nd.left).value160 self.delete(nd.value - 1, nd.left, nd)161 162 def __contains__(self, v: int) -> bool:163 return self.find_r(v - 1) == v164 165 class node:166 def __init__(self, v, p):167 self.value = v168 self.pivot = p169 self.left = None170 self.right = None171 172 def debug(self):173 def debug_info(nd_):174 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)175 176 def debug_node(nd):177 re = []178 179 if nd.left:180 re += debug_node(nd.left)181 if nd.value: 182 re.append(debug_info(nd))183 if nd.right:184 re += debug_node(nd.right)185 return re186 187 print("Debug - root =", self.root.value - 1, debug_node(self.root)[:50])188 189 def debug_list(self):190 def debug_node(nd):191 re = []192 193 if nd.left:194 re += debug_node(nd.left)195 if nd.value: 196 re.append(nd.value - 1)197 if nd.right:198 re += debug_node(nd.right)199 return re200 return debug_node(self.root)[:-1]201 202 203def main():204 import sys205 206 input = sys.stdin.readline207 208 n = 2 ** 20209 q = int(input())210 a = [-1] * n211 bt = BalancingTree(21)212 inf = float('inf')213 214 for i in range(n + 1):215 bt.append(i)216 217 for _ in range(q):218 ti, xi = map(int, input().split())219 220 if ti == 1:221 h = xi222 h %= n223 index = inf224 225 if h in bt:226 index = h227 else:228 pos = bt.find_r(h)229 230 if pos == n:231 index = bt.min232 else:233 index = pos234 235 a[index] = xi236 bt.delete(index)237 else:238 print(a[xi % n])239 240 241if __name__ == "__main__":242 main()243