ABC477 F - Count Cells in a Window

窓内のマス数

考え方

グリッド面積がもう少し小さければ、二次元累積和で $O(MN+Q)$ で解ける。
これを、高速化と省メモリ化すればよい。

まず、クエリで必要となる累積和の値は、高々 $4Q$ ヶ所である。
よって、クエリ先読みをして、その場所の一覧を用意、ソートする。

これを上にあるものから $1$ 段ずつ、順に求めていく。
ある行の情報を考えるとき、前の行でのデータにその行の黒マス情報を加算する。
これは、結局のところ区間加算である。
つまり、遅延segment木でデータを持っておけば、$O(\log M)$ でその処理は完了する。
その遅延segment木で区間和を取れば、あるマスを基準にして左上にある黒マス個数が求まる。

それらを全て map か何かに入れておき、それを用いて二次元累積和の処理をすればよい。

計算量は、以下の4つの合計となる。

よって、全体として $O(M+(N+Q)\log M+Q\log Q)$ である。

入力例1での動作

入力を受け取る。

n: 3
m: 6
q: 3

各行の黒マス区間:
[2, 4]
[1, 1]
[4, 6]

queries:
1 2 1 4
2 3 3 6
1 1 5 6

$S(i,j)$ を、上から $i$ 行、左から $j$ 列の範囲にある黒マスの個数とする。
各クエリ $(A,B,C,D)$ の答えは、二次元累積和と同様に $S(B,D)-S(A-1,D)-S(B,C-1)+S(A-1,C-1)$ で求められる。

したがって、この入力で必要な $S(i,j)$ だけを事前に列挙する。

上から順に行を追加していく。
各時点で、列ごとの「ここまでに黒マスだった回数」を遅延segment木で管理する。
必要な $j$ について、先頭から $j$ 列分の区間和を求める。

処理済み行数 新しく加える区間 列 $1$ から $6$ の黒マス数 この段階で必要な累積和
$0$ なし $(0,0,0,0,0,0)$ $S(0,0)=0,\ S(0,4)=0,\ S(0,6)=0$
$1$ $[2,4]$ $(0,1,1,1,0,0)$ $S(1,2)=1,\ S(1,4)=3,\ S(1,6)=3$
$2$ $[1,1]$ $(1,1,1,1,0,0)$ $S(2,0)=0,\ S(2,4)=4$
$3$ $[4,6]$ $(1,1,1,2,1,1)$ $S(3,2)=2,\ S(3,6)=7$

これで、各クエリに必要な累積和が揃う。

クエリ 1 2 1 4 の答えは $S(2,4)-S(0,4)-S(2,0)+S(0,0)=4$ となる。

クエリ 2 3 3 6 の答えは $S(3,6)-S(1,6)-S(3,2)+S(1,2)=7-3-2+1=3$ となる。

クエリ 1 1 5 6 の答えは $S(1,6)-S(0,6)-S(1,4)+S(0,4)=3-0-3+0=0$ となる。

したがって、出力は順に $4,3,0$ となる。

注意点

黒マスの個数は、int 型からはみ出る可能性がある。
long long 型を用いること。

別解

特になし。