题目分析
求联通块但是R和C很大,用bfs很明显会超时,因此需要对其进行离散化,这一点我在我的前几篇博文中提过,但是本题还涉及到一个新的知识点,离散化之后还需要知道每个连通块中cell的个数,因此还需要一点小技巧,就是利用2个数组存储中间值。
#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 505;
#define LL long long
#define PII pair <int, int>
bool vis[maxn][maxn];
int R, C, n;
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
int x1[maxn], y1[maxn], x2[maxn], y2[maxn];
PII P[maxn];
map <int, int> X, Y;
LL ans[maxn];
void solve(){
scanf("%d%d%d", &R, &C, &n);
int num1 = 0; x1[++num1] = 1; x1[++num1] = R; //注意边界值要加上,想一想为什么
int num2 = 0; y1[++num2] = 1; y1[++num2] = C;
for(int i = 0; i < n; i++){
scanf("%d%d", &P[i].first, &P[i].second);
x1[++num1] = P[i].first;
y1[++num2] = P[i].second;
}
sort(x1+1, x1+num1+1);
int xnum = unique(x1+1, x1+num1+1) - x1 - 1;
sort(y1+1, y1+num2+1);
int ynum = unique(y1+1, y1+num2+1) - y1 - 1;
X.clear(), Y.clear();
int xx = 0, yy = 0;
for(int i = 1; i <= xnum; i++){
if(x1[i] - x1[i-1] != 1)
x2[++xx] = x1[i] - x1[i-1] - 1;
x2[++xx] = 1;
X[x1[i]] = xx;
}
for(int i = 1; i <= ynum; i++){
if(y1[i] - y1[i-1] != 1)
y2[++yy] = y1[i] - y1[i-1] - 1;
y2[++yy] = 1;
Y[y1[i]] = yy;
}
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++) vis[X[P[i].first]][Y[P[i].second]] = true;
// printf("%d, %d\n", X[P[0].first], Y[P[0].second]);
queue <PII> que;
int flag = 0;
// printf("xx = %d, yy = %d\n", xx, yy);
for(int i = 1; i <= xx; i++){
for(int j = 1; j <= yy; j++) if(!vis[i][j]) {
LL cnt = 0;
que.push(make_pair(i, j));
vis[i][j] = true;
while(!que.empty()){
PII cur = que.front(); que.pop();
cnt += (LL)x2[cur.first]*y2[cur.second];
// printf("x = %d, y = %d\n", x2[cur.first], y2[cur.second]);
for(int k = 0; k < 4; k++){
int nx = cur.first + dir[k][0];
int ny = cur.second + dir[k][1];
if(nx < 1 || nx > xx || ny < 1 || ny > yy || vis[nx][ny]) continue;
vis[nx][ny] = 1;
que.push(make_pair(nx, ny));
}
}
ans[flag++] = cnt;
}
}
sort(ans, ans+flag);
printf("%d\n", flag);
for(int i = 0; i < flag; i++){
if(i) printf(" ");
printf("%I64d", ans[i]);
}
printf("\n");
}
int main(){
int T;
scanf("%d", &T);
for(int kase = 1; kase <= T; kase++){
printf("Case #%d:\n", kase);
solve();
}
return 0;
}