E - Grid Filling Editorial by en_translator
This problem can be solved in a total of \(O(HWN)\) time if you know:
- \(\operatorname{count}[k][l][x]:=\) the number of squares \((i,j)\) such that \(k\lt i\leq H, l\lt j\leq W\) with numbers \(x\) written on them.
Indeed, when the squares from \((k+1,l+1)\) to \((k+h,l+w)\) are blacked out, there are
\[\operatorname{count}[0][0][x]-\operatorname{count}[k][l][x]+\operatorname{count}[k][l+w][x]-\operatorname{count}[k+h][l+w][x]+\operatorname{count}[k+h][l][x]\]
squares with \(x\) written on them that remain not blacked-out, so the answer for \((k,l)\) can be found in an \(O(N)\) time.
In order to find \(\operatorname{count}[k][l][x]\), it is sufficient to find the two-dimensional cumulative sums.
We describe the specific way.
We can let
- \(\operatorname{count}[k][l][x]=\) \(1\) if \((k+1,j+1)\) has \(x\) written on it, and \(0\) otherwise
in a total of \(O(HWN)\) time. By iterating \((k,j,x)\) in a proper order while updating as \(\operatorname{count}[k][l][x]\leftarrow\operatorname{count}[k][l][x]+\operatorname{count}[k][l+1][x]\), we can let
- \(\operatorname{count}[k][l][x]:=\) the number of squares \((k+1,l)\) such that \(k\lt l\leq W\) with \(x\) written on them.
Similarly, by updating as \(\operatorname{count}[k][l][x]\leftarrow\operatorname{count}[k][l][x]+\operatorname{count}[k+1][l][x]\), we can obtain the desired \(\operatorname{count}\).
Therefore, the problem has been solved in a total of \(O(HWN)\) time.
A sample code follows.
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
int main() {
using namespace std;
unsigned H, W, N, h, w;
cin >> H >> W >> N >> h >> w;
// count[i][j][x] = 1 if square (i + 1, j + 1) has x written on it, and 0 otherwise
vector count(H, vector(W, vector<unsigned>(N)));
for (auto &&row : count) {
for (auto &&grid : row) {
unsigned long A;
cin >> A;
++grid[A - 1];
}
// sentinel
row.emplace_back(N);
}
// sentinel
count.emplace_back(W + 1, vector<unsigned>(N));
// two-dimensional cumulative sums
std::inclusive_scan(rbegin(count), rend(count), rbegin(count), [](auto &&i, auto &&j) {
const auto vector_plus{[](auto &&i, auto &&j) {
vector<unsigned> ret;
transform(begin(i), end(i), begin(j), back_inserter(ret), plus<>{});
return ret;
}};
std::inclusive_scan(rbegin(j), rend(j), rbegin(j), vector_plus);
vector<vector<unsigned>> ret;
transform(begin(i), end(i), begin(j), back_inserter(ret), vector_plus);
return ret;
});
// board[i][j][x] = the number of squares below and in the left of square (i, j), with x written on them
for (unsigned i{}; i + h <= H; ++i) {
for (unsigned j{}; j + w <= W; ++j) {
unsigned ans{};
// increment the answer by 1 if there is one or more not-blacked-out squares with x written on them
for (unsigned x{}; x < N; ++x)
ans += count[0][0][x] + count[i + h][j][x] + count[i][j + w][x] !=
count[i][j][x] + count[i + h][j + w][x];
cout << ans << " ";
}
cout << endl;
}
return 0;
}
posted:
last update: