結果
問題 | No.649 ここでちょっとQK! |
ユーザー | kohei2019 |
提出日時 | 2022-03-01 00:41:26 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 654 ms / 3,000 ms |
コード長 | 13,551 bytes |
コンパイル時間 | 143 ms |
コンパイル使用メモリ | 82,128 KB |
実行使用メモリ | 100,228 KB |
最終ジャッジ日時 | 2024-07-07 03:46:24 |
合計ジャッジ時間 | 12,583 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 37 ms
56,424 KB |
testcase_01 | AC | 39 ms
56,812 KB |
testcase_02 | AC | 41 ms
56,488 KB |
testcase_03 | AC | 178 ms
90,724 KB |
testcase_04 | AC | 312 ms
99,184 KB |
testcase_05 | AC | 316 ms
98,964 KB |
testcase_06 | AC | 346 ms
99,528 KB |
testcase_07 | AC | 40 ms
56,248 KB |
testcase_08 | AC | 43 ms
56,564 KB |
testcase_09 | AC | 42 ms
56,244 KB |
testcase_10 | AC | 40 ms
56,172 KB |
testcase_11 | AC | 37 ms
56,428 KB |
testcase_12 | AC | 355 ms
88,036 KB |
testcase_13 | AC | 353 ms
87,728 KB |
testcase_14 | AC | 354 ms
87,696 KB |
testcase_15 | AC | 391 ms
88,244 KB |
testcase_16 | AC | 346 ms
88,300 KB |
testcase_17 | AC | 383 ms
88,604 KB |
testcase_18 | AC | 404 ms
90,588 KB |
testcase_19 | AC | 440 ms
92,760 KB |
testcase_20 | AC | 470 ms
92,704 KB |
testcase_21 | AC | 509 ms
94,732 KB |
testcase_22 | AC | 523 ms
95,740 KB |
testcase_23 | AC | 559 ms
96,416 KB |
testcase_24 | AC | 608 ms
97,768 KB |
testcase_25 | AC | 600 ms
98,688 KB |
testcase_26 | AC | 654 ms
100,228 KB |
testcase_27 | AC | 83 ms
76,780 KB |
testcase_28 | AC | 81 ms
76,504 KB |
testcase_29 | AC | 82 ms
76,092 KB |
testcase_30 | AC | 360 ms
87,272 KB |
testcase_31 | AC | 360 ms
88,620 KB |
testcase_32 | AC | 38 ms
56,028 KB |
testcase_33 | AC | 37 ms
56,584 KB |
testcase_34 | AC | 37 ms
56,264 KB |
testcase_35 | AC | 37 ms
55,756 KB |
ソースコード
#非再帰の平衡二分木 import copy class Node: """ノード Attributes: key (any): ノードのキー。比較可能なものであれば良い。(1, 4)などタプルも可。 val (any): ノードの値。 lch (Node): 左の子ノード。 rch (Node): 右の子ノード。 bias (int): 平衡度。(左部分木の高さ)-(右部分木の高さ)。 size (int): 自分を根とする部分木の大きさ """ def __init__(self, key, val): self.key = key self.val = val self.lch = None self.rch = None self.bias = 0 self.size = 1 class AVLTree: """非再帰AVL木 Attributes: root (Node): 根ノード。初期値はNone。 valdefault (any): ノード値のデフォルト値。デフォルトではNone。(数値、リストなど可) """ def __init__(self,valdefault=None): self.root = None self.valdefault = valdefault def rotate_left(self, v): u = v.rch u.size = v.size v.size -= u.rch.size + 1 if u.rch is not None else 1 v.rch = u.lch u.lch = v if u.bias == -1: u.bias = v.bias = 0 else: u.bias = 1 v.bias = -1 return u def rotate_right(self, v): u = v.lch u.size = v.size v.size -= u.lch.size + 1 if u.lch is not None else 1 v.lch = u.rch u.rch = v if u.bias == 1: u.bias = v.bias = 0 else: u.bias = -1 v.bias = 1 return u def rotateLR(self, v): u = v.lch t = u.rch t.size = v.size v.size -= u.size - (t.rch.size if t.rch is not None else 0) u.size -= t.rch.size + 1 if t.rch is not None else 1 u.rch = t.lch t.lch = u v.lch = t.rch t.rch = v self.update_bias_double(t) return t def rotateRL(self, v): u = v.rch t = u.lch t.size = v.size v.size -= u.size - (t.lch.size if t.lch is not None else 0) u.size -= t.lch.size + 1 if t.lch is not None else 1 u.lch = t.rch t.rch = u v.rch = t.lch t.lch = v self.update_bias_double(t) return t def update_bias_double(self, v): if v.bias == 1: v.rch.bias = -1 v.lch.bias = 0 elif v.bias == -1: v.rch.bias = 0 v.lch.bias = 1 else: v.rch.bias = 0 v.lch.bias = 0 v.bias = 0 def insert(self, key, val=None): """挿入 指定したkeyを挿入する。valはkeyのノード値。 Args: key (any): キー。 val (any): 値。(指定しない場合はvaldefaultが入る) Note: 同じキーがあった場合は上書きする。 """ if val == None: val = copy.deepcopy(self.valdefault) if self.root is None: self.root = Node(key, val) return v = self.root history = [] while v is not None: if key < v.key: history.append((v, 1)) v = v.lch elif v.key < key: history.append((v, -1)) v = v.rch elif v.key == key: v.val = val return p, pdir = history[-1] if pdir == 1: p.lch = Node(key, val) else: p.rch = Node(key, val) while history: v, direction = history.pop() v.bias += direction v.size += 1 new_v = None b = v.bias if b == 0: break if b == 2: u = v.lch if u.bias == -1: new_v = self.rotateLR(v) else: new_v = self.rotate_right(v) break if b == -2: u = v.rch if u.bias == 1: new_v = self.rotateRL(v) else: new_v = self.rotate_left(v) break if new_v is not None: if len(history) == 0: self.root = new_v return p, pdir = history.pop() p.size += 1 if pdir == 1: p.lch = new_v else: p.rch = new_v while history: p, pdir = history.pop() p.size += 1 def delete(self, key): """削除 指定したkeyの要素を削除する。 Args: key (any): キー。 Return: bool: 指定したキーが存在するならTrue、しないならFalse。 """ v = self.root history = [] while v is not None: if key < v.key: history.append((v, 1)) v = v.lch elif v.key < key: history.append((v, -1)) v = v.rch else: break else: return False if v.lch is not None: history.append((v, 1)) lmax = v.lch while lmax.rch is not None: history.append((lmax, -1)) lmax = lmax.rch v.key = lmax.key v.val = lmax.val v = lmax c = v.rch if v.lch is None else v.lch if history: p, pdir = history[-1] if pdir == 1: p.lch = c else: p.rch = c else: self.root = c return True while history: new_p = None p, pdir = history.pop() p.bias -= pdir p.size -= 1 b = p.bias if b == 2: if p.lch.bias == -1: new_p = self.rotateLR(p) else: new_p = self.rotate_right(p) elif b == -2: if p.rch.bias == 1: new_p = self.rotateRL(p) else: new_p = self.rotate_left(p) elif b != 0: break if new_p is not None: if len(history) == 0: self.root = new_p return True gp, gpdir = history[-1] if gpdir == 1: gp.lch = new_p else: gp.rch = new_p if new_p.bias != 0: break while history: p, pdir = history.pop() p.size -= 1 return True def member(self, key): """キーの存在チェック 指定したkeyがあるかどうか判定する。 Args: key (any): キー。 Return: bool: 指定したキーが存在するならTrue、しないならFalse。 """ v = self.root while v is not None: if key < v.key: v = v.lch elif v.key < key: v = v.rch else: return True return False def getval(self, key): """値の取り出し 指定したkeyの値を返す。 Args: key (any): キー。 Return: any: 指定したキーが存在するならそのオブジェクト。存在しなければvaldefault """ v = self.root while v is not None: if key < v.key: v = v.lch elif v.key < key: v = v.rch else: return v.val self.insert(key) return self[key] # def lower_bound(self, key): """下限つき探索 指定したkey以上で最小のキーを見つける。[key,inf)で最小 Args: key (any): キーの下限。 Return: any: 条件を満たすようなキー。そのようなキーが一つも存在しないならNone。 """ ret = None v = self.root while v is not None: if v.key >= key: if ret is None or ret > v.key: ret = v.key v = v.lch else: v = v.rch return ret def upper_bound(self, key): """上限つき探索 指定したkey未満で最大のキーを見つける。[-inf,key)で最大 Args: key (any): キーの上限。 Return: any: 条件を満たすようなキー。そのようなキーが一つも存在しないならNone。 """ ret = None v = self.root while v is not None: if v.key < key: if ret is None or ret < v.key: ret = v.key v = v.rch else: v = v.lch return ret def find_kth_element(self, k): """小さい方からk番目の要素を見つける Args: k (int): 何番目の要素か(0オリジン)。 Return: any: 小さい方からk番目のキーの値。 """ v = self.root s = 0 while v is not None: t = s+v.lch.size if v.lch is not None else s if t == k: return v.key elif t < k: s = t+1 v = v.rch else: v = v.lch return None def key_kth(self,key): ''' Args: keyが何番目に小さい要素かを調べる Return: int(keyが存在しなければNone) ''' v = self.root kth = 0 f = False while v is not None: if key < v.key: v = v.lch elif v.key < key: kth += 1+v.lch.size if v.lch is not None else 1 v = v.rch else: kth += v.lch.size if v.lch is not None else 0 f = True break if f: return kth else: return None def getmin(self): ''' Return: any: 存在するキーの最小値 ''' if len(self) == 0: raise('empty') ret = None v = self.root while True: ret = v v = v.lch if v == None: break return ret.key def getmax(self): ''' Return: any: 存在するキーの最大値 ''' if len(self) == 0: raise('empty') ret = None v = self.root while True: ret = v v = v.rch if v == None: break return ret.key def popmin(self): ''' 存在するキーの最小値をpopする Return: any: popした値 ''' if len(self) == 0: raise('empty') ret = None v = self.root while True: ret = v v = v.lch if v == None: break del self[ret.key] return ret.key def popmax(self): ''' 存在するキーの最大値をpopする Return: any: popした値 ''' if len(self) == 0: raise('empty') ret = None v = self.root while True: ret = v v = v.rch if v == None: break del self[ret.key] return ret.key def popkth(self,k): ''' 存在するキーの小さい方からk番目をpopする Return: any: popした値 ''' key = self.find_kth_element(k) del self[key] return key def get_key_val(self): ''' Return: dict: 存在するキーとノード値をdictで出力 ''' retdict = dict() for i in range(len(self)): key = self.find_kth_element(i) val = self[key] retdict[key] = val return retdict def values(self): for i in range(len(self)): yield self[self.find_kth_element(i)] def keys(self): for i in range(len(self)): yield self.find_kth_element(i) def items(self): for i in range(len(self)): key = self.find_kth_element(i) yield key,self[key] def __iter__(self): return self.keys() def __contains__(self, key): return self.member(key) def __getitem__(self, key): return self.getval(key) def __setitem__(self, key, val): return self.insert(key, val) def __delitem__(self, key): return self.delete(key) def __bool__(self): return self.root is not None def __len__(self): return self.root.size if self.root is not None else 0 def __str__(self): return str(type(self))+'('+str(self.get_key_val())+')' Q,K = map(int,input().split()) avl = AVLTree() ans = [] for i in range(Q): ls = list(map(int,input().split())) if ls[0] == 1: avl.insert((ls[1],i)) else: if len(avl) < K: ans.append(-1) else: ans.append(avl.popkth(K-1)[0]) print(*ans,sep='\n')