公式

D - 照明パネルと額縁 / Lighting Panels and Picture Frames 解説 by sounansya


行が \(A_i\) 以上 \(B_i\) 以下、列が \(C_i\) 以上 \(D_i\) 以下であるマスの状態を反転する操作は \(2\) 次元 imos 法を用いることで \(O(HW+N)\) 時間で計算することができます。

この計算したグリッドを元に、点灯したパネルの連結成分ごとに分解します。

1.指定された領域内にある、点灯しているマスの個数

上で計算したグリッドの状態を元に愚直に数え上げれば良いです。二次元累積和を用いることで \(O(1)\) 時間で計算できるようにすることもできます。

2.指定された領域内にある、点灯しているマスの個数

点灯したパネルの連結成分ごとに、その連結成分が全て長方形の領域に含まれるか判定し、完全に含まれる領域の個数を求めれば良いです。

実装例(Python3)

from collections import deque

h, w, n = map(int, input().split())
g = [[False] * (w + 1) for _ in range(h + 1)]
for _ in range(n):
    a, b, c, d = map(int, input().split())
    a, c = a - 1, c - 1
    g[a][c] ^= True
    g[a][d] ^= True
    g[b][c] ^= True
    g[b][d] ^= True
for i in range(h):
    for j in range(w + 1):
        g[i + 1][j] ^= g[i][j]
for i in range(h + 1):
    for j in range(w):
        g[i][j + 1] ^= g[i][j]
visited = [[False] * (w) for _ in range(h)]
grids = []
for stx in range(h):
    for sty in range(w):
        if visited[stx][sty] or not g[stx][sty]:
            continue
        q = deque()
        visited[stx][sty] = True
        q.append((stx, sty))
        xs = []
        ys = []
        while q:
            x, y = q.popleft()
            xs.append(x)
            ys.append(y)
            for dx, dy in ((-1, 0), (1, 0), (0, -1), (0, 1)):
                xx, yy = x + dx, y + dy
                if (
                    not (0 <= xx < h and 0 <= yy < w)
                    or visited[xx][yy]
                    or not g[xx][yy]
                ):
                    continue
                visited[xx][yy] = True
                q.append((xx, yy))
        grids.append((min(xs), max(xs), min(ys), max(ys)))
m = int(input())
for _ in range(m):
    p, q, r, s = map(int, input().split())
    p, r = p - 1, r - 1
    ans1 = 0
    for x in range(p, q):
        for y in range(r, s):
            if g[x][y]:
                ans1 += 1
    ans2 = 0
    for minx, maxx, miny, maxy in grids:
        if p <= minx and maxx < q and r <= miny and maxy < s:
            ans2 += 1
    print(ans1, ans2)

投稿日時:
最終更新: