#1487 : 岛屿3
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
H国正在进行一项持续N周的填海造岛工程。整片工程海域可以被看作是1000x1000的网格。
每周都有一块1x1的单位方格海域被填成陆地。如果我们将连成一片的陆地(一块单位方格与它上下左右4个单位方格是相连的)视为岛屿,H国想监测每周末整片海域中一共存在有多少个岛屿,以及这些岛屿的总面积和总周长各是多少。
假设工程持续三周,第一周被填的海域坐标是(0, 0),那么第一周结束后有1座岛屿、总面积是1、总周长是4:
#..
...
...
第二周被填的海域坐标是(1, 1),那么第二周结束后有2座岛屿、总面积是2、总周长是8:
#..
.#.
...
第三周被填的海域坐标是(1, 0),那么第三周结束后有1座岛屿、总面积是3、总周长是8:
#..
##.
...
你能完成这项任务么?
输入
第一行包含一个整数N,表示工程持续的周数。(1 <= N <= 100000)
以下N行每行包含两个整数x和y,表示当周被填的海域坐标。(0 <= x, y < 1000)
输出
输出N行,每行包含3个整数,依次是当周末岛屿的数量、总面积和总周长。
样例输入
3
0 0
1 1
1 0
样例输出
1 1 4
2 2 8
1 3 8
这里联通集我们用并查集处理一下,二维的点集,可以把x,y映射到1000x+y上构成一维的。因为xy范围都在1000内,用并查集以便于统计联通集的个数,每次放入一个新块之后,把周边的相邻的点都先存到一个vector里,然后挨着判断一下是不是一个集合,如果不是一个集合,那么联通集总数就要-1,如果不相邻,总数就+1,新增周长可以用4-2*相邻的边数来计算。
二维转变一维,我们一般写的入门并查集,都是一维,这里我们通过1005*x+y转成一维,为什么取1005呢,比1000大就行了,这里的数据规模实际大于了1000*1000,所以开大一点才可以A
import java.util.Scanner;
public class hihocoder_1487_岛屿3 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
f = new int[1005*1005+5];
for(int i=0;i<=1005*1005;i++)
f[i] = -1;//初始化海
for(int i=1;i<=n;i++) {
int a = 1005*in.nextInt()+in.nextInt();
f[a] = a;
insert(a, i);
}
}
static int n;
static int[] f;
static int cnt=0,c=0;
static int find(int x) {
if(f[x]==x)//x = 1005*x+y
return x;
return f[x] = find(f[x]);
}
static void insert(int x,int m) {
cnt++;
int k=0;
k+=union(x,x-1005);
k+=union(x,x+1);
k+=union(x,x+1005);
k+=union(x,x-1);
c+=4-2*k;
System.out.println(cnt+" "+m+" "+c);
}
static int union(int x,int y) {
if(y<0 || y>1005*1005 || f[y]==-1)
return 0;
int u = find(f[x]);
int v = find(f[y]);
// System.out.println(x+" "+y);
if(u!=v) {
f[u] = v;
cnt--;
}
return 1;
}
}