結果
| 問題 |
No.1282 Display Elements
|
| コンテスト | |
| ユーザー |
neterukun
|
| 提出日時 | 2020-11-06 21:50:48 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 586 ms / 2,000 ms |
| コード長 | 6,505 bytes |
| コンパイル時間 | 278 ms |
| コンパイル使用メモリ | 82,280 KB |
| 実行使用メモリ | 102,528 KB |
| 最終ジャッジ日時 | 2024-07-22 12:41:13 |
| 合計ジャッジ時間 | 6,217 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 24 |
ソースコード
from random import random
import sys
input = sys.stdin.buffer.readline
class TreapNode:
"""Treapのノード定義"""
def __init__(self, val):
self.val = val
self.priority = random()
self.size = 1
self.sum_ = val
self.parent, self.right, self.left = None, None, None
class Treap:
"""平衡二分探索木: 値の検索、挿入、削除などクエリ処理をO(logN)で実行する"""
def __init__(self):
self.root = None
def search(self, val: int) -> bool:
"""値の検索: 集合に値valを持つノードが存在するか"""
ptr = self.root
while ptr is not None:
if val < ptr.val:
ptr = ptr.left
elif val > ptr.val:
ptr = ptr.right
else:
return True
return False
def insert(self, val: int) -> bool:
"""値の挿入: 集合に値valを持つノードを挿入する"""
if self.root is None:
self.root = TreapNode(val)
return True
# ノードの挿入
ptr = self.root
while True:
if val < ptr.val:
if ptr.left is None:
ptr.left = TreapNode(val)
ptr.left.parent = ptr
ptr = ptr.left
break
ptr = ptr.left
else:
if ptr.right is None:
ptr.right = TreapNode(val)
ptr.right.parent = ptr
ptr = ptr.right
break
ptr = ptr.right
# 木の回転によってヒープ性を保つ
if ptr.priority < 0.2: # 木の回転をサボる
while (ptr.parent is not None) and (ptr.parent.priority > ptr.priority):
if ptr.parent.right == ptr:
self._rotate_left(ptr.parent)
else:
self._rotate_right(ptr.parent)
if ptr.parent is None:
self.root = ptr
tmp = ptr.parent
while tmp is not None:
self.update(tmp)
tmp = tmp.parent
return True
def delete(self, val: int) -> True:
"""値の削除: 集合から値valを持つノードを削除する"""
if self.root is None:
return False
ptr = self.root
tmp = None
while ptr is not None:
if val < ptr.val:
ptr = ptr.left
elif val > ptr.val:
ptr = ptr.right
else:
tmp = ptr
if (ptr.right is not None) and ptr.right.val == val:
ptr = ptr.right
elif (ptr.left is not None) and ptr.left.val == val:
ptr = ptr.left
else:
break
ptr = tmp
# 木の回転によって削除したいノードを葉に持っていく
while (ptr.left is not None) or (ptr.right is not None):
if ptr.left is None:
self._rotate_left(ptr)
elif ptr.right is None:
self._rotate_right(ptr)
elif ptr.left.priority < ptr.right.priority:
self._rotate_right(ptr)
else:
self._rotate_left(ptr)
if self.root == ptr:
self.root = ptr.parent
# ノードの削除
if ptr.left is None and ptr.right is None:
if ptr == self.root:
self.root = None
elif ptr.parent.left == ptr:
ptr.parent.left = None
else:
ptr.parent.right = None
tmp = ptr.parent
while tmp is not None:
self.update(tmp)
tmp = tmp.parent
return True
def _rotate_left(self, ptr):
"""木の左回転を行う"""
w = ptr.right
w.parent = ptr.parent
if w.parent is not None:
if w.parent.left == ptr:
w.parent.left = w
else:
w.parent.right = w
ptr.right = w.left
if ptr.right is not None:
ptr.right.parent = ptr
ptr.parent = w
w.left = ptr
if ptr == self.root:
self.root = w
self.root.parent = None
self.update(ptr)
self.update(w)
def _rotate_right(self, ptr):
"""木の右回転を行う"""
w = ptr.left
w.parent = ptr.parent
if w.parent is not None:
if w.parent.right == ptr:
w.parent.right = w
else:
w.parent.left = w
ptr.left = w.right
if ptr.left is not None:
ptr.left.parent = ptr
ptr.parent = w
w.right = ptr
if ptr == self.root:
self.root = w
self.root.parent = None
self.update(ptr)
self.update(w)
def update(self, ptr):
"""部分木の情報を更新する"""
ptr.size = 1
ptr.sum_ = ptr.val
if ptr.left is not None:
ptr.size += ptr.left.size
ptr.sum_ += ptr.left.sum_
if ptr.right is not None:
ptr.size += ptr.right.size
ptr.sum_ += ptr.right.sum_
def get_sum(self, ind):
ptr = self.root
sum_ = 0
while True:
l_size = 0
if ptr.left is not None:
l_size = ptr.left.size
if ind < l_size:
ptr = ptr.left
continue
if ind == l_size:
sum_ += ptr.val
if ptr.left is not None:
sum_ += ptr.left.sum_
return sum_
sum_ += ptr.val
if ptr.left is not None:
sum_ += ptr.left.sum_
ptr = ptr.right
ind -= l_size + 1
def search_lt(self, val):
nd = self.root
sz = 0
while nd is not None:
if nd.val < val:
if nd.left is not None:
sz += nd.left.size
sz += 1
nd = nd.right
else: nd = nd.left
return sz
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
a = sorted(a)
tp = Treap()
ans = 0
for vala, valb in zip(a, b):
tp.insert(valb)
ans += tp.search_lt(vala)
print(ans)
neterukun