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: 処理する区間の長さ

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)