F - Count Cells in a Window Editorial by en_translator
The input gives closed intervals, but we will regard them as half-open intervals.
It is difficult to naively count them. Consider queries given in the form \([0, X) \times [L, R)\), and let \(S(X, L, R)\) be the answer.
Once we can solve this, the original problem can be answered as \(S(B, C, D) - S(A, C, D)\).
(Of course, \(L\) can also be eliminated via two-dimensional cumulative sums, but this time we will represent in this form. When solving, such an elimination should also be in-scope.)
However, even computing this is not straightforward.
We employ the technique called scanline algorithm.
(Among several possible variants of scanline algorithm) Here we will prefetch all queries, sort them in ascending order of \(X\), and process them.
This approach is effective when finding the answer directly for some \(X\) is difficult, but the difference from \(X \to X+1\) can be tracked fast.
This time, turning \(X\to X+1\) adds row \(X\) to the rectangle.
Manage how many black cells are in column \(j\), up to row \(X\). The answer can be answered as a segment sum on this array.
Row \(X\) has black cells in segment \([L_X,R_X)\), so we want to add \(1\) to each column in this segment.
Therefore, it suffices to support segment-wise addition and segment-sum retrieval, which can be done with a lazy segment tree. Specifically, it suffices to manage pairs representing (value, length of segment).
Sample code (PyPy)
import sys
from atcoder.lazysegtree import LazySegTree
input = sys.stdin.buffer.readline
def op(a, b):
return (a[0] + b[0], a[1] + b[1])
def mapping(f, x):
return (x[0] + f * x[1], x[1])
def composition(f, g):
return f + g
n, m, q = map(int, input().split())
lr = [tuple(map(int, input().split())) for _ in range(n)]
qs = [[] for _ in range(n + 1)]
for i in range(q):
u, d, l, r = map(int, input().split())
qs[d].append((l - 1, r, i, 1))
qs[u - 1].append((l - 1, r, i, -1))
seg = LazySegTree(op, (0, 0), mapping, composition, 0, [(0, 1)] * m)
ans = [0] * q
for x in range(n + 1):
if x:
l, r = lr[x-1]
seg.apply(l - 1, r, 1)
for l, r, i, sgn in qs[x]:
ans[i] += sgn * seg.prod(l, r)[0]
print(*ans, sep="\n")