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

模拟赛题讲解[32]


模拟赛题讲解[32]

来自 yukuai26 2023-08-04 noi.ac #3271

题目描述

给定一个 \(H\)\(W\) 列的矩阵,矩阵中的点一开始均为白色,然后将指定的 \(N\) 个点染成黑色,询问有多少个 \(3 \times 3\)的区域中有恰好 \(i\)个黑色点 \(0 \le i \le 9\)

输入格式

输入共 \(N+1\)行,第一行三个整数,分别是 \(H,W,N\),含义如题目所示。

接下来 \(N\)行,每行两个整数 \(x,y\),表示将坐标为 \(x,y\) 的点染成黑色。

输出格式

输出共 \(10\) 行,每行一个数,第 \(i\)行代表有多少个 \(3 \times 3\)的区域中恰好有 \(i-1\)个黑色点。

输入样例

4 5 8
1 1
1 4
1 5
2 3
3 1
3 2
3 4
4 4

输出样例

0
0
0
2
4
0
0
0
0
0

数据范围

保证没有任何一个点被重复染色。

\(3 \le H, W \le 10^9,~0 \le N \le \min(10^5, H \times W),~1 \le x_i,y_i \le H,W\)

题解

这个破题居然折腾了我好久,真服了。

我的做法是枚举每个点周围的 \(8\) 个点,如果不存在就加一个虚点。

然后枚举所有的点,计算以其为中心的矩形的答案(虚点不算进贡献里)

时间复杂度 \(\mathcal{O}(9N)\)

代码:(最失败的一份代码,留下作为教训)

#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))
#define np(x,y) (make_pair(a[i].Fi + x, a[i].Se + y))
#define Fi first
#define Se second

int n,m,W,H,ans[15]; pii a[9 * N]; map<pii, char> mp;
bool check(pii x) { return *lower_bound(a + 1, a + 1 + n, x) == x; }
// int pos(pii x) { return lower_bound(a + 1, a + 1 + n, x) - a; }
bool safe(pii x) { return x.Fi >= 1 && x.Fi <= W && x.Se >= 1 && x.Se <= H; }
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> W >> H >> n;
    for(int i = 1; i <= n; i++) cin >> a[i].Fi >> a[i].Se;
    sort(a + 1, a + 1 + n);
    for(int i = 1; i <= n; i++)
    {
        for(int c = -1; c <= 1; c++)
            for(int d = -1; d <= 1; d++) {
                pii tmp = np(c,d);
                if(safe(tmp) && !check(tmp) && !mp[tmp])
                    a[n + (++m)] = tmp, mp[tmp] = 1;
            }
    }
    for(int i = 1; i <= n + m; i++)
    {
        if(safe(np(1,1)) && safe(np(-1,-1)))
        {
            int cnt = 0;
            for(int c = -1; c <= 1; c++)
                for(int d = -1; d <= 1; d++)
                    if(check(np(c,d))) ++cnt;
            ++ans[cnt];
        }
    }
    ans[0] = (W - 2) * (H - 2);
    for(int i = 1; i <= 9; i++) ans[0] -= ans[i];
    for(int i = 0; i <= 9; i++) cout << ans[i] << '\n';
    return 0;
}

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