公式

E - ペイントドロップ / Paint Drop 解説 by sounansya


各行について独立に考えます。

各行では、各クエリで \(W\) 列の区間に対してペイントされ、新しくペイントされたマスに対するスコアの総和を求められれば良いです。

これは、各マスに対して「現在のマスから(自分を含め)右にあるマスの中でまだ塗られていないマスのうち最も近いマス」を保持することで高速にシミュレーションすることができます。また、これは Union-Find と似たようなアルゴリズムを用いることで実装することができます。

実装例(Python3)

import sys

input = sys.stdin.readline
H, W = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(H)]
Q = int(input())
queries = []
for t in range(Q):
    r, c, d = map(int, input().split())
    queries.append((r - 1, c - 1, d))
ans = [0] * Q


def solve_row(row_index, row_values):
    parent = list(range(W + 1))

    def find(x):
        while parent[x] != x:
            parent[x] = parent[parent[x]]
            x = parent[x]
        return x

    for t, (r, c, d) in enumerate(queries):
        rem = d - abs(row_index - r)
        if rem < 0:
            continue
        l = max(0, c - rem)
        rr = min(W, c + rem + 1)
        x = find(l)
        while x < rr:
            ans[t] += row_values[x]
            parent[x] = find(x + 1)
            x = parent[x]


for i in range(H):
    solve_row(i, A[i])
print("\n".join(map(str, ans)))

投稿日時:
最終更新: