嘘~ 正在从服务器偷取页面 . . .


[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;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录