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)


戻る