結果
| 問題 |
No.878 Range High-Element Query
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-06-10 19:04:19 |
| 言語 | Crystal (1.14.0) |
| 結果 |
AC
|
| 実行時間 | 666 ms / 2,000 ms |
| コード長 | 3,118 bytes |
| コンパイル時間 | 16,150 ms |
| コンパイル使用メモリ | 313,512 KB |
| 実行使用メモリ | 16,056 KB |
| 最終ジャッジ日時 | 2025-01-02 14:56:32 |
| 合計ジャッジ時間 | 22,332 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 18 |
ソースコード
class SegmentTree(T)
@sz : Int64
#配列、単位元、比較用の演算をブロックで渡す
def initialize(ary : Array(T), @defv : T, &block : T, T -> T)
n = ary.size.to_i64
sz = 1_i64
while sz < n
sz *= 2
end
@tree = Array(T).new(sz*2-1,@defv)
@sz = sz
@compare_proc = block
i = 0
#葉に元の値を入れる
while i < n
@tree[i+sz-1] = ary[i]
i += 1
end
i = sz - 2
while i >= 0
#親に上って子を比較しながら値を入れる
@tree[i] = @compare_proc.call(@tree[i*2+1], @tree[i*2+2])
i -= 1
end
end
#全ての葉を返す
def tree
@tree[@sz-1..-1]
end
#indexを指定して値を返す
def [] (i : Int64)
i += @sz - 1
@tree[i]
end
#数値による置換
def update(i : Int64, val : T)
i += @sz - 1
#葉を更新する
@tree[i] = val
while i > 0
i = (i-1) // 2
#親に上って更新する
@tree[i] = @compare_proc.call(@tree[i*2+1], @tree[i*2+2])
end
end
#ブロックによる置換
def update(i : Int64)
i += @sz - 1
#葉を更新する
@tree[i] = yield(@tree[i])
while i > 0
i = (i-1) // 2
#親に上って更新する
@tree[i] = @compare_proc.call(@tree[i*2+1], @tree[i*2+2])
end
end
#特定区間の演算結果を返す
def get(a : Int64, b : Int64, now = 0_i64, l = 0_i64, r = -1_i64)
r = @sz if r < 0
return @defv if (b <= l || r <= a)
return @tree[now] if (a <= l && r <= b)
vl = get(a,b,now*2+1,l,(l+r)//2)
vr = get(a,b,now*2+2,(l+r)//2,r)
return @compare_proc.call(vl, vr)
end
end
#Binary Indexed Tree
#0~iの区間和を求める
#区間加算対応
class BIT
def initialize(size : Int64)
#1-indexにする
@size = size + 1
@bit = Array(Array(Int64)).new(2) {Array(Int64).new(@size,0_i64)}
end
#半開区間
def add(l : Int64, r : Int64, x : Int64)
l += 1
r += 1
add_sub(0,l,-x*(l-1))
add_sub(0,r,x*(r-1))
add_sub(1,l,x)
add_sub(1,r,-x)
end
def get(i)
i += 1
return get_sub(0,i) + get_sub(1,i) * i
end
#l以上r以下(閉区間)
def get(l : Int64, r : Int64)
get(r) - get(l-1)
end
def add_sub(p, i : Int64, x : Int64)
while i < @size
@bit[p][i] += x
i += (i & -i)
end
end
def get_sub(p, i : Int64)
res = 0_i64
while i > 0
res += @bit[p][i]
i -= (i & -i)
end
return res
end
end
n, q = read_line.split.map(&.to_i64)
a = read_line.split.map(&.to_i64)
query = Array(Tuple(Int64, Int64, Int64)).new
q.times do |i|
_, l, r = read_line.split.map(&.to_i64)
query << {r - 1, l - 1, i}
end
query.sort!
tree1 = SegmentTree(Int64).new(a, 0_i64) { |a, b| a > b ? a : b }
tree2 = BIT.new(n)
k = 0_i64
ans = Array.new(q, 0_i64)
a.each_with_index do |v, i|
i = i.to_i64
l = (0_i64..i).bsearch do |j|
tree1.get(j, i + 1) <= v
end
tree2.add(l.not_nil!, i + 1, 1_i64)
while k < q && query[k][0] == i
ans[query[k][2]] = tree2.get(query[k][1], query[k][1])
k += 1
end
end
puts ans.join("\n")