题目
Description
H国正在进行一项持续N周的填海造岛工程。整片工程海域可以被看作是1000x1000的网格。
每周都有一块1x1的单位方格海域被填成陆地。如果我们将连成一片的陆地(一块单位方格与它上下左右4个单位方格是相连的)视为岛屿,H国想监测每周末整片海域中一共存在有多少个岛屿,以及这些岛屿的总面积和总周长各是多少。
假设工程持续三周,第一周被填的海域坐标是(0, 0),那么第一周结束后有1座岛屿、总面积是1、总周长是4:
#…
…
…
第二周被填的海域坐标是(1, 1),那么第二周结束后有2座岛屿、总面积是2、总周长是8:
#…
.#.
…
第三周被填的海域坐标是(1, 0),那么第三周结束后有1座岛屿、总面积是3、总周长是8:
#…
##.
…
你能完成这项任务么?
Input
第一行包含一个整数N,表示工程持续的周数。(1 <= N <= 100000)
以下N行每行包含两个整数x和y,表示当周被填的海域坐标。(0 <= x, y < 1000)
Output
输出N行,每行包含3个整数,依次是当周末岛屿的数量、总面积和总周长。
Sample Input
3
0 0
1 1
1 0
Sample Output
1 1 4
2 2 8
1 3 8
题解
每填一个网格(x,y),sum++,area++,L+=4。
然后对其四个方向的网格进行查询是否已被填。
四个方向的网格每被填一个,则L-=2。
再对四个方向中被填的网格进行查询是否与当前网格在一个并查集中,不在则sum–。
AC代码
#include <bits/stdc++.h>
using namespace std;const int maxn=1e6+7;
int N,par[maxn];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
bool vis[1100][1100];
inline int getid(int x,int y){return 1000*x+y;}void init()
{for(int i=0;i<maxn;i++) par[i]=i;memset(vis,false,sizeof(vis));
}
inline int find(int x)
{return par[x]==x?x:par[x]=find(par[x]);
}
inline bool same(int x,int y){return find(x)==find(y);}
void unit(int x,int y)
{x=find(x);y=find(y);if(x==y) return ;par[x]=y;
}int main()
{int n;while(~scanf("%d",&n)){init();int sum=0;int area=0;int L=0;for(int i=0;i<n;i++){int x,y;scanf("%d%d",&x,&y);vis[x][y]=true;L+=4;area++;sum++;for(int j=0;j<4;j++){int fx=x+dir[j][0];int fy=y+dir[j][1];if(fx>=0 && fx<1000 && fy>=0 && fy<1000){if(vis[fx][fy]){L-=2;if(same(getid(fx,fy),getid(x,y))){continue;}unit(getid(fx,fy),getid(x,y));sum--;}}}printf("%d %d %d\n",sum,area,L);}}
}