Range Update Query (RUQ)
概要
以下のクエリが処理できるセグメント木の実装
-
\(a_l, a_{l+1}, ..., a_{r-1}\) の値を \(x\) に更新
-
\(a_i\) の現在の値を計算
計算方法
セグメント木で各区間 \([l, r)\) において、その区間全体が更新された時刻 \(t\) とその値 \(x\) のtuple値 \((t, x)\) を持つ。
時刻 \(t\) に区間 \([l, r)\) を値 \(x\) で更新する際は、区間 \([l, r)\) を覆う最小個数の区間をtuple値 \((t, x)\) で更新する。
\(a_i\) の値を取得する際は、 \(i\) を含む全ての区間 \([l, r)\) のtuple値をチェックし、最も \(t\) が大きいtuple値 \((t, x)\) を求め、 その \(x\) を現在の値とする。
計算量
-
区間更新: \(O(\log N)\)
-
値取得: \(O(\log N)\)
実装
# N: 処理する区間の長さ
N = ...
N0 = 2**(N-1).bit_length()
data = [None]*(2*N0)
INF = (-1, 2**31-1)
# 区間[l, r+1)の値をvに書き換える
# vは(t, value)という値にする (新しい値ほどtは大きくなる)
def update(l, r, v):
L = l + N0; R = r + N0
while L < R:
if R & 1:
R -= 1
data[R-1] = v
if L & 1:
data[L-1] = v
L += 1
L >>= 1; R >>= 1
# a_iの現在の値を取得
def _query(k):
k += N0-1
s = INF
while k >= 0:
if data[k]:
s = max(s, data[k])
k = (k - 1) // 2
return s
# これを呼び出す
def query(k):
return _query(k)[1]
Verified
-
AOJ: "DSL_2_D: Range Query - Range Update Query (RUQ)": source (Python3, 0.96sec)