結果
| 問題 |
No.3134 二分探索木
|
| コンテスト | |
| ユーザー |
tomerun
|
| 提出日時 | 2025-05-02 21:37:01 |
| 言語 | Crystal (1.14.0) |
| 結果 |
AC
|
| 実行時間 | 250 ms / 2,000 ms |
| コード長 | 5,564 bytes |
| コンパイル時間 | 10,920 ms |
| コンパイル使用メモリ | 314,468 KB |
| 実行使用メモリ | 39,168 KB |
| 最終ジャッジ日時 | 2025-05-02 21:37:20 |
| 合計ジャッジ時間 | 14,378 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 15 |
ソースコード
n = read_line.to_i
a = read_line.split.map(&.to_i)
tree = RBST(Tuple(Int32, Int32)).new
b = Array.new(n, 0)
c = Array.new(n, 0)
parent = Array.new(n, -1)
children = Array.new(n) { [] of Int32 }
tree.insert({a[0], 0})
1.upto(n - 1) do |i|
tree.insert({a[i], i})
rank = tree.rank({a[i], i})
if rank == 0
parent[i] = tree.nth(1)[1]
elsif rank == i
parent[i] = tree.nth(i - 1)[1]
else
p0 = tree.lower({a[i], i}).not_nil![1]
p1 = tree.upper({a[i], i}).not_nil![1]
if b[p0] < b[p1]
parent[i] = p1
else
parent[i] = p0
end
end
b[i] = b[parent[i]] + 1
children[parent[i]] << i
end
n.times.to_a.sort_by { |i| -b[i] }.each do |i|
c[i] = 1
children[i].each do |j|
c[i] += c[j]
end
end
puts b.join(" ")
puts c.map { |i| i - 1 }.join(" ")
class RBST(T)
class Node(T)
@left : Node(T) | Nil
@right : Node(T) | Nil
property :left, :right
getter :val, :size
def initialize(@val : T)
@left = nil
@right = nil
@size = 1
end
def height
if left = @left
lh = left.height
else
lh = 0
end
if right = @right
rh = right.height
else
rh = 0
end
return {lh, rh}.max + 1
end
def fix_size
@size = 1
if left = @left
@size += left.size
end
if right = @right
@size += right.size
end
end
def to_s(io : IO)
to_s(io, 0)
end
def to_s(io : IO, level : Int32)
if left = @left
left.to_s(io, level + 1)
end
io << " " * level * 2 << @val << "\n"
if right = @right
right.to_s(io, level + 1)
end
end
end
@root : Node(T) | Nil
def initialize
@root = nil
@rnd = Random.new
end
def insert(v : T)
@root = insert(@root, v)
end
def insert(node : Node(T) | Nil, v : T) : Node(T)
return Node(T).new(v) if !node
if @rnd.rand(node.size + 1) == 0
return insert_root(node, v)
end
if v < node.val
node.left = insert(node.left, v)
else
node.right = insert(node.right, v)
end
node.fix_size
return node
end
def insert_root(node : Node(T) | Nil, v : T) : Node(T)
return Node(T).new(v) if !node
if v < node.val
node.left = insert_root(node.left, v)
return rotate_right(node)
else
node.right = insert_root(node.right, v)
return rotate_left(node)
end
end
def rotate_right(node : Node(T)) : Node(T)
top = node.left.not_nil!
mid = top.right
top.right = node
node.left = mid
node.fix_size
top.fix_size
return top
end
def rotate_left(node : Node(T)) : Node(T)
top = node.right.not_nil!
mid = top.left
top.left = node
node.right = mid
node.fix_size
top.fix_size
return top
end
def clear
@root = nil
end
def remove(v : T) : Bool
new_root, found = remove(@root, v)
if found
@root = new_root
return true
else
return false
end
end
def remove(node : Node(T) | Nil, v : T) : Tuple(Node(T) | Nil, Bool)
return {nil, false} if !node
if v == node.val
return {meld(node.left, node.right), true}
elsif v < node.val
new_child, found = remove(node.left, v)
if found
node.left = new_child
node.fix_size
end
else
new_child, found = remove(node.right, v)
if found
node.right = new_child
node.fix_size
end
end
return {node, found}
end
def meld(left : Node(T) | Nil, right : Node(T) | Nil) : Node(T) | Nil
return right if !left
return left if !right
if @rnd.rand(left.size + right.size) < left.size
left.right = meld(left.right, right)
left.fix_size
return left
else
right.left = meld(left, right.left)
right.fix_size
return right
end
end
def find(v : T) : Node(T) | Nil
cur = @root
while cur
if v == cur.val
return cur
elsif v < cur.val
cur = cur.left
else
cur = cur.right
end
end
return nil
end
def nth(n : Int32) : T
# 0-indexed
cur = @root
while cur
ln = cur.left
lc = ln ? ln.size : 0
if lc > n
cur = cur.left
elsif lc < n
cur = cur.right
n -= lc + 1
else
break
end
end
if cur
return cur.val
else
raise Exception.new("cannot fine")
end
end
def rank(v : T) : Int32
# 0-indexed, not count equivalent values
cur = @root
ret = 0
while cur
if v <= cur.val
cur = cur.left
else
if left = cur.left
ret += left.size
end
ret += 1
cur = cur.right
end
end
return ret
end
def lower(v : T) : T | Nil
# largest value smaller than v
cur = @root
ret = nil
while cur
if cur.val < v
ret = cur.val
cur = cur.right
else
cur = cur.left
end
end
return ret
end
def upper(v : T) : T | Nil
# smallest value larger than v
cur = @root
ret = nil
while cur
if cur.val > v
ret = cur.val
cur = cur.left
else
cur = cur.right
end
end
return ret
end
def size
if root = @root
return root.size
else
return 0
end
end
def height
if root = @root
root.height
else
0
end
end
def to_s(io : IO)
if root = @root
root.to_s(io, 0)
else
io << "nil\n"
end
end
end
tomerun