Problem Description
We have a grid with H rows and W columns. At first, all cells were painted white.
Snuke painted N of these cells. The i-th ( 1≤i≤N ) cell he painted is the cell at the ai-th row and bi-th column.
Compute the following:
For each integer j ( 0≤j≤9 ), how many subrectangles of size 3×3 of the grid contains exactly j black cells, after Snuke painted N cells?
Constraints
- 3≤H≤109
- 3≤W≤109
- 0≤N≤min(105,H×W)
- 1≤ai≤H (1≤i≤N)
- 1≤bi≤W (1≤i≤N)
- (ai,bi)≠(aj,bj) (i≠j)
Input
The input is given from Standard Input in the following format:
H W N
a1 b1
:
aN bNOutput
Print 10 lines. The (j+1)-th ( 0≤j≤9 ) line should contain the number of the subrectangles of size 3×3 of the grid that contains exactly j black cells.
Example
Sample Input 1
4 5 8
1 1
1 4
1 5
2 3
3 1
3 2
3 4
4 4Sample Output 1
0
0
0
2
4
0
0
0
0
0There are six subrectangles of size 3×3. Two of them contain three black cells each, and the remaining four contain four black cells each.
Sample Input 2
10 10 20
1 1
1 4
1 9
2 5
3 10
4 2
4 7
5 9
6 4
6 6
6 7
7 1
7 3
7 7
8 1
8 5
8 10
9 2
10 4
10 9Sample Output 2
4
26
22
10
2
0
0
0
0
0Sample Input 3
1000000000 1000000000 0
Sample Output 3
999999996000000004
0
0
0
0
0
0
0
0
0
题意:给一个长为 H 宽为 W 的网状矩形,开始时所有的格子都是白色的,现在给出 n 个格子的坐标,要把他们涂黑,将格子涂黑后,依次输出有多少个 3*3 大小的子矩形包含 0~9 个黑色格子
思路:
由于 h、w 极大,暴力一定会超时,注意到要涂黑的 n 个格子最大为 1E5,那么可以从涂黑的格子考虑
注意到每个涂黑的格子在以其为中心的 3*3 矩形中贡献了 1 个黑色,那么可以枚举所有的黑色格子,统计其贡献度,即以其为中心 3*3 的矩形贡献度+1,然后再去枚举所有涉及到的格子,由于 n 最大为 1E5,那么最坏情况下只需枚举 1E5*9 个格子
可以发现,对于给定的 h、w 的矩形,其有 (h-2)*(w-2) 个 3*3 的矩形,即小矩形的中心不可能在矩形的边上,故当统计完贡献度后,枚举所有不在矩形边上的格子,将其贡献度记录到桶中,并记录所有涉及到的总数,就是 3*3 矩形中存在 1~9 个格子的个数
最后再用总的矩形个数减去 1~9 个黑格个数就是 0 个黑格个数
由于要统计出现过的格子的坐标,使用 map+pair 极为方便
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 1000000+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;
LL bucket[10];
pair<int,int> node[N];
map<pair<int,int>,int> mp;
int main(){
LL h,w,n;
scanf("%lld%lld%lld",&h,&w,&n);
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&node[i].first,&node[i].second);
mp[node[i]]=1;//涂黑的格子贡献度为1
}
for(int i=1;i<=n;i++){
for(int j=0;j<8;j++){//统计涂黑的格子周围格子的贡献度
int nx=node[i].first+dx[j];
int ny=node[i].second+dy[j];
if(nx>=1&&nx<=h&&ny>=1&ny<=w){//越界判断
pair<int,int> temp(nx,ny);
mp[temp]++;
}
}
}
LL sum=0;
LL tot=(h-2)*(w-2);//总共的矩形数
map<pair<int,int>,int>::iterator it;
for(it=mp.begin();it!=mp.end();it++){//枚举所有涉及到的格子
int x=it->first.first;
int y=it->first.second;
int val=it->second;
if(x>=2&&x<=h-1&&y>=2&y<=w-1){//统计除去最外一圈的格子
bucket[val]++;
sum++;
}
}
bucket[0]=tot-sum;//为0的数量是总共的矩形减去所有非零的矩形
for(int i=0;i<=9;i++)
printf("%lld\n",bucket[i]);
return 0;
}