結果
問題 | No.1439 Let's Compare!!!! |
ユーザー |
|
提出日時 | 2022-10-05 00:13:59 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 789 ms / 2,000 ms |
コード長 | 10,464 bytes |
コンパイル時間 | 402 ms |
コンパイル使用メモリ | 82,304 KB |
実行使用メモリ | 106,740 KB |
最終ジャッジ日時 | 2024-12-30 15:31:51 |
合計ジャッジ時間 | 8,652 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 17 |
ソースコード
import sysinput = lambda: sys.stdin.readline().rstrip()class AVLNodeSet:__slots__ = ('key', 'size', 'left', 'right', 'balance')def __init__(self, key):self.key = keyself.size = 1self.left = Noneself.right = Noneself.balance = 0class AVLTreeSet:__slots__ = ('node', '__iter')__LEFT, __RIGHT = 1, -1def __init__(self, V=[]) -> None:# Make a new AVLTree.# V: Iterableself.node = Noneself.__build(V)def __build(self, V) -> None:for v in sorted(V):self.add(v)def __rotate_L(self, node: AVLNodeSet) -> AVLNodeSet:u = node.leftu.size = node.sizenode.size -= 1 if u.left is None else u.left.size + 1node.left = u.rightu.right = nodeif u.balance == 1:u.balance, node.balance = 0, 0else:u.balance, node.balance = -1, 1return udef __rotate_R(self, node: AVLNodeSet) -> AVLNodeSet:u = node.rightu.size = node.sizenode.size -= 1 if u.right is None else u.right.size + 1node.right = u.leftu.left = nodeif u.balance == -1:u.balance, node.balance = 0, 0else:u.balance, node.balance = 1, -1return udef __update_balance(self, node: AVLNodeSet) -> None:# nodeはnew_nodeif node.balance == 1:node.right.balance, node.left.balance = -1, 0elif node.balance == -1:node.right.balance, node.left.balance = 0, 1else:node.right.balance, node.left.balance = 0, 0node.balance = 0def __rotate_LR(self, node: AVLNodeSet) -> AVLNodeSet:# A E# / \ / \# B C -> B A# /\ /\ /\# D E D F1F2 C# /\# F1 F2# # node: AB = node.leftE = B.rightE.size = node.sizeers = 0 if E.right is None else E.right.sizenode.size -= B.size - ersB.size -= ers + 1B.right = E.leftE.left = Bnode.left = E.rightE.right = nodeself.__update_balance(E)return Edef __rotate_RL(self, node: AVLNodeSet) -> AVLNodeSet:C = node.rightD = C.leftD.size = node.sizedls = 0 if D.left is None else D.left.sizenode.size -= C.size - dlsC.size -= dls + 1C.left = D.rightD.right = Cnode.right = D.leftD.left = nodeself.__update_balance(D)return Ddef add(self, key) -> bool:'''add key. / O(logN)'''if self.node is None:self.node = AVLNodeSet(key)return Truepnode = self.nodepath = []while pnode is not None:if key < pnode.key:path.append((pnode, self.__LEFT))pnode = pnode.leftelif key > pnode.key:path.append((pnode, self.__RIGHT))pnode = pnode.rightelse:return Falsepnode, di = path[-1]if di == self.__LEFT:pnode.left = AVLNodeSet(key)else:pnode.right = AVLNodeSet(key)while path:new_node = Nonepnode, di = path.pop()pnode.size += 1pnode.balance += diif pnode.balance == 0:breakif pnode.balance == 2: # pnodeの左部分木が茂りすぎif pnode.left.balance == -1:# LR2重回転: nodeの右側が茂っている場合new_node = self.__rotate_LR(pnode)else:# LL1重回転: nodeの左側が茂っている場合new_node = self.__rotate_L(pnode)breakelif pnode.balance == -2: # pnodeの右部分木が茂りすぎif pnode.right.balance == 1:# RL2重回転: nodeの左側が茂っている場合new_node = self.__rotate_RL(pnode)else:# RR1重回転: nodeの右側が茂っている場合new_node = self.__rotate_R(pnode)break# else: 最初にpnode.balanceを更新したので、何もせずcontinueしてOKif new_node is not None:if path:gnode, gdi = path.pop()gnode.size += 1if gdi == self.__LEFT:gnode.left = new_nodeelse:gnode.right = new_nodeelse:self.node = new_nodereturnwhile path:path.pop()[0].size += 1return Truedef remove(self, key) -> bool:'''Remove key. / O(logN)'''if self.discard(key):return Trueraise KeyError(f'{key} is not exist.')def discard(self, key) -> bool:'''Discard key. / O(logN)'''path = []node = self.nodewhile node is not None:if key < node.key:path.append((node, self.__LEFT))node = node.leftelif key > node.key:path.append((node, self.__RIGHT))node = node.rightelse:breakelse:return Falseif node.left is not None and node.right is not None:path.append((node, self.__LEFT))lmax = node.leftwhile lmax.right is not None:path.append((lmax, self.__RIGHT))lmax = lmax.rightnode.key = lmax.keynode = lmaxcnode = node.right if node.left is None else node.leftif path:pnode, di = path[-1]if di == self.__LEFT:pnode.left = cnodeelse:pnode.right = cnodeelse:self.node = cnodereturn Truewhile path:new_node = Nonepnode, di = path.pop()pnode.balance -= dipnode.size -= 1if pnode.balance == 2:if pnode.left.balance < 0:new_node = self.__rotate_LR(pnode)else:new_node = self.__rotate_L(pnode)elif pnode.balance == -2:if pnode.right.balance > 0:new_node = self.__rotate_RL(pnode)else:new_node = self.__rotate_R(pnode)elif pnode.balance != 0:breakif new_node is not None:if not path:self.node = new_nodereturngnode, gdir = path[-1]if gdir == self.__LEFT:gnode.left = new_nodeelse:gnode.right = new_nodeif new_node.balance != 0:breakwhile path:path.pop()[0].size -= 1return Truedef count(self, key) -> int:'''Return the number of key. / O(logN)'''return 1 if key in self else 0def le(self, key):'''Find the largest element <= key, or None if it doesn't exist. / O(logN)'''res = Nonenode = self.nodewhile node is not None:if key < node.key:node = node.leftelif key > node.key:res = node.keynode = node.rightelse:res = node.keybreakreturn resdef lt(self, key):'''Find the largest element < key, or None if it doesn't exist. / O(logN)'''res = Nonenode = self.nodewhile node is not None:if key < node.key:node = node.leftelif key > node.key:res = node.keynode = node.rightelse:breakreturn resdef ge(self, key):'''Find the smallest element >= key, or None if it doesn't exist. / O(logN)'''res = Nonenode = self.nodewhile node is not None:if key < node.key:res = node.keynode = node.leftelif key > node.key:node = node.rightelse:res = node.keybreakreturn resdef gt(self, key):'''Find the smallest element > key, or None if it doesn't exist. / O(logN)'''res = Nonenode = self.nodewhile node is not None:if key < node.key:res = node.keynode = node.leftelif key > node.key:node = node.rightelse:breakreturn resdef index(self, key) -> int:'''Count the number of elements < key. / O(logN)'''indx = 0node = self.nodewhile node:if key < node.key:node = node.leftelif key > node.key:indx += 1 if node.left is None else node.left.size + 1node = node.rightelse:indx += 0 if node.left is None else node.left.sizebreakreturn indxdef index_right(self, key) -> int:'''Count the number of elements <= key. / O(logN)'''indx = 0node = self.nodewhile node:if key < node.key:node = node.leftelif key > node.key:indx += 1 if node.left is None else node.left.size + 1node = node.rightelse:indx += 1 if node.left is None else node.left.size + 1breakreturn indxdef pop(self, p=-1):'''Return and Remove max element or a[p]. / O(logN)'''if p < 0:p += self.__len__()x = self.__kth_elm(p)self.discard(x)return xdef popleft(self):'''Return and Remove min element. / O(logN)'''return self.pop(0)def __kth_elm(self, k):if k < 0:k += self.__len__()now = 0node = self.nodewhile node is not None:t = now if node.left is None else now + node.left.sizeif t < k:now = t + 1node = node.rightelif t > k:node = node.leftelse:return node.keyraise IndexError(f'k={k}, len={self.__len__()}')def __contains__(self, x):node = self.nodewhile node:if x < node.key:node = node.leftelif x > node.key:node = node.rightelse:return Truereturn Falsedef __getitem__(self, x):return self.__kth_elm(x)def __iter__(self):self.__iter = 0return selfdef __next__(self):if self.__iter == self.__len__():raise StopIterationres = self.__getitem__(self.__iter)self.__iter += 1return resdef __reversed__(self):for i in range(self.__len__()):yield self.__getitem__(-i-1)def __len__(self):return 0 if self.node is None else self.node.sizedef __bool__(self):return self.node is not Nonedef __repr__(self):return '{' + ', '.join(map(str, self)) + '}'def __str__(self):return '{' + ', '.join(map(str, self)) + '}'# ----------------------- #n = int(input())S = list(map(int, input()))T = list(map(int, input()))comp = [i for i in range(n) if S[i] != T[i]]avl = AVLTreeSet(comp)q = int(input())for _ in range(q):c, x, y = input().split()x, y = int(x), int(y)x -= 1if c == 'S':S[x] = yelse:T[x] = yif S[x] != T[x]:avl.add(x)else:avl.discard(x)if avl:keta = avl[0]if S[keta] < T[keta]:print('<')else:print('>')else:print('=')