[ABC045D] Snuke’s Coloring 题解
题目链接:[ABC045D] Snuke’s Coloring
题意:
给定一个 $H$ 行 $W$ 列的矩形,再给定矩形上 $N$ 个黑格子的坐标。
对于每个 $0\le i\le9$ ,求出有多少个 $3\times3$ 的子矩阵包含有恰好 $i$ 个黑格子。
$3 \leq H \leq 10^9, ~3 \leq W \leq 10^9,~0 \leq N \leq \min \left(10^5, H \times W\right)$
记 $f_{i,j}$ 表示点 $(i,j)$ 到点 $(i + 2, j + 2)$ 的矩阵的答案。
由于 $H,W$ 都很大,但 $N$ 很小,而每个黑点至多对周围的 $8$ 个格子产生贡献
那么我们只需要把所有涉及贡献的 $f$ 计算一下,显然其他的都是 $0$ ,并且可以 $\mathcal{O}(1)$ 计算。
时间复杂度 $\mathcal{O}(n \log n)$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
typedef pair<int,int> pii;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e5 + 15))
int H,W,n,ans[N]; map<pii,int> mp;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
cin >> H >> W >> n;
for(int i = 1, x, y; i <= n; i++)
{
cin >> x >> y;
for(int tx = x - 2; tx <= x; tx++)
for(int ty = y - 2; ty <= y; ty++)
if(tx > 0 && tx < H - 1 && ty > 0 && ty < W - 1) ++mp[{tx, ty}];
}
for(auto && i : mp) ++ans[i.second];
ans[0] += (H - 2) * (W - 2) - mp.size();
for(int i = 0; i <= 9; i++) cout << ans[i] << '\n';
return 0;
}