Official
E - 店舗売上管理 / Store Sales Management Editorial by admin
Qwen3-Coder-480B概要
この問題は、複数の店舗の売上情報を管理し、区間和の取得と一点更新の操作を高速に処理するものです。
考察
この問題では以下の2種類のクエリを処理する必要があります。
- 区間 \([L, R]\) の売上額の合計を求める(区間和)
- 店舗 \(X\) の売上額を新しい値 \(V\) に更新する(一点更新)
素朴な方法として、毎回区間和を愚直に計算することもできますが、その場合1回の区間和クエリで最大 \(O(N)\) かかり、全体で \(O(Q \times N)\) となり、制約 \(N, Q \leq 2 \times 10^5\) のもとでは時間内に処理できません(TLE)。
そこで、区間和の取得と一点更新を効率的に行えるデータ構造「Binary Indexed Tree(BIT)」または「Fenwick Tree」というテクニックを使用します。BIT を使うことで、どちらの操作も \(O(\log N)\) で行え、全体で \(O(Q \log N)\) で処理可能です。
また、BIT は1-indexedで管理するのが一般的なので、配列のインデックスに注意しながら実装する必要があります。
アルゴリズム
Binary Indexed Tree(BIT) を使用して、以下の処理を行います。
初期化フェーズ
- 各店舗の初期売上額 \(S_i\) を BIT に追加します。これは各要素に対して
updateを行うことで実現できます。
クエリ処理
- クエリ1(区間和):
- BIT の
range_sum(L, R)メソッドを呼び出し、区間 \([L, R]\) の和を取得して出力します。
- BIT の
- クエリ2(一点更新):
- まず変更前の値 \(S[X-1]\) と新しい値 \(V\) の差分 \(delta = V - S[X-1]\) を求めます。
- BIT 上で
update(X, delta)を行い、BIT の値を更新します。 - 配列 \(S\) も実際に更新しておきます。
BIT の内部では、以下のような操作を行っています:
update(idx, delta):位置idxに値deltaを加算(実際には差分を加算)prefix_sum(idx):位置 \(1\) からidxまでの累積和を取得range_sum(l, r):区間 \([l, r]\) の和をprefix_sum(r) - prefix_sum(l - 1)で求める
計算量
- 時間計算量: \(O((N + Q) \log N)\)
- 空間計算量: \(O(N)\)
実装のポイント
- BIT は1-indexedで扱うので、配列の添字に注意(例:店舗 \(X\) は BIT 内では
Xとして扱う) - 売上額の更新時は「差分」を BIT に加えることで効率的に更新できる
- Python では
sys.stdin.readlineを使うことで入力速度を向上させる
ソースコード
import sys
input = sys.stdin.readline
class BIT:
def __init__(self, n):
self.n = n
self.tree = [0] * (n + 1)
def update(self, idx, delta):
while idx <= self.n:
self.tree[idx] += delta
idx += idx & (-idx)
def prefix_sum(self, idx):
res = 0
while idx > 0:
res += self.tree[idx]
idx -= idx & (-idx)
return res
def range_sum(self, l, r):
return self.prefix_sum(r) - self.prefix_sum(l - 1)
N, Q = map(int, input().split())
S = list(map(int, input().split()))
bit = BIT(N)
for i in range(N):
bit.update(i + 1, S[i])
for _ in range(Q):
query = list(map(int, input().split()))
if query[0] == 1:
_, L, R = query
print(bit.range_sum(L, R))
else:
_, X, V = query
delta = V - S[X - 1]
S[X - 1] = V
bit.update(X, delta)
この解説は qwen3-coder-480b によって生成されました。