Day 015-Q4 — 2次元BIT

2026-04-28 赤色 Master / Phase 8+ ★★★★★★★★★ 多次元データ構造

問題

N×N グリッドに対し: add x y v で値加算、sum x1 y1 x2 y2 で矩形和。

制約

$1 \le N \le 1000$
$1 \le Q \le 2 \times 10^5$
v は整数(負も可)

入出力例

入力例 1

4 5
add 2 3 5
add 1 1 3
sum 1 1 4 4
sum 2 2 4 4
add 3 3 -2

出力例 1

8
5

ヒント (段階的開示)

ヒント1: 方向性
2次元BIT は行・列に BIT を適用。点加算・矩形和ともに $O(\log^2 N)$。
ヒント2: アプローチ
矩形和は包除原理: query(x2,y2) - query(x1-1,y2) - query(x2,y1-1) + query(x1-1,y1-1)。
ヒント3: 誘導
外側で行 i、内側で列 j を BIT 走査。i, j ともに $i \mathrel{+}= i \& (-i)$。

模範解答 (Python)

import sys
input = sys.stdin.readline

class BIT2D:
    def __init__(self, n):
        self.n = n
        self.tree = [[0] * (n + 1) for _ in range(n + 1)]
    def update(self, x, y, v):
        i = x
        while i <= self.n:
            j = y
            while j <= self.n:
                self.tree[i][j] += v
                j += j & (-j)
            i += i & (-i)
    def query(self, x, y):
        s = 0; i = x
        while i > 0:
            j = y
            while j > 0:
                s += self.tree[i][j]
                j -= j & (-j)
            i -= i & (-i)
        return s
    def rect_sum(self, x1, y1, x2, y2):
        return (self.query(x2, y2)
                - self.query(x1 - 1, y2)
                - self.query(x2, y1 - 1)
                + self.query(x1 - 1, y1 - 1))

def main():
    N, Q = map(int, input().split())
    bit = BIT2D(N)
    out = []
    for _ in range(Q):
        line = input().split()
        if line[0] == 'add':
            x, y, v = int(line[1]), int(line[2]), int(line[3])
            bit.update(x, y, v)
        else:
            x1, y1, x2, y2 = int(line[1]), int(line[2]), int(line[3]), int(line[4])
            out.append(bit.rect_sum(x1, y1, x2, y2))
    print('\n'.join(map(str, out)))

main()

Step-by-Step 解説

11次元BIT
更新: $i \mathrel{+}= i \& (-i)$、クエリ: $i \mathrel{-}= i \& (-i)$。
22次元拡張
外側で行、内側で列を走査。
3矩形クエリ
2次元の包除原理。
4計算量
各 $O(\log^2 N)$、N=1000, Q=2×10^5 で 2×10^7 操作。

よくあるミス

ミス原因正しい書き方
配列サイズ N+11-indexed[[0]*(N+1) for _ in range(N+1)]
包除の符号ミス4 項の符号+,−,−,+ で確実に
int overflow (C)Python は不問

次のステップ

  • 3次元BIT、2次元 Segment Tree との比較

自己評価

自分の回答

気づき・メモ