#1487 : 岛屿3
-
3 0 0 1 1 1 0
样例输出
-
1 1 4 2 2 8 1 3 8
描述
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个整数,依次是当周末岛屿的数量、总面积和总周长。
题意非常简单,1000*1000的矩阵,一开始是空的,每次不重复的放一个点,求4向联通集的个数,总面积和总周长。
这里联通集我们用并查集处理一下,二维的点集,可以把x,y映射到1000x+y上构成一维的。因为xy范围都在1000内,用并查集以便于统计联通集的个数,每次放入一个新块之后,把周边的相邻的点都先存到一个vector里,然后挨着判断一下是不是一个集合,如果不是一个集合,那么联通集总数就要-1,如果不相邻,总数就+1,新增周长可以用4-2*相邻的边数来计算。
这个题调试了半天,2.30比赛结束,我2.31提交上去1A了,T_T。问题出在我这一堆for循环上,有一个地方手抖敲错了。。。for(int k=0;k<4;i++),我调了将近半个小时,就是没看出来哪里不对,程序运行到这就卡住了,比赛结束的一瞬间我把i改成k交上去就A了。天命如此……自己太水,不想说什么了,这又让我想起来几次区域赛打铁的经历,跟这次大同小异,有毒呀。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <stack>
using namespace std;
//x*1000+y;
int par[1000005];
int tall[1000005];
void init(int n){
for(int i=1;i<=n;i++){
par[i]=i;
tall[i]=0;
}
}
int find_root(int x){
if(par[x]==x){
return x;
}
else{
return par[x]=find_root(par[x]);
}
}
void unite(int x,int y){
x=find_root(x);
y=find_root(y);
if(x==y)return;
if(tall[x]<tall[y]){
par[x]=y;
}
else{
par[y]=x;
if(tall[x]==tall[y])tall[x]++;
}
}
bool same(int x,int y){
return find_root(x)==find_root(y);
}
int F[1005][1005];
int d[4][2]={1,0,0,1,0,-1,-1,0};
int n;
bool cango(int x,int y){
return x>=0&&x<1000&&y>=0&&y<1000;
}
int main()
{
while(cin>>n){
memset(F,0,sizeof(F));
init(1000009);
int num=0;//数量
int S=0;//面积
int L=0;//周长
for(int i=0;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
F[x][y]=1;
int V=x*1000+y+1;
int find_a_new=1;//四周都是空的
int chongbian=0;//重合边数量
vector<int>P;//所有边界点
P.clear();
for(int k=0;k<4;k++){
int nx=x+d[k][0];
int ny=y+d[k][1];
if(cango(nx,ny)){
int nV=nx*1000+ny+1;
if(F[nx][ny]==1){
P.push_back(nV);
chongbian++;
find_a_new=0;//没找到新的
if(same(nV,V)){
//chongbian++;
//unite(nV,V);
}
else{
//unite(nV,V);
//chongbian++;
}
}
else{
}
}
else{
}
// cout<<"fuck"<<endl;
}
if(find_a_new==1){
num++;
L+=4;
}
else{
unite(P[0],V);
// cout<<"stat "<<P.size()<<endl;
//cout<<P[0]<<" !!! "<<P[1]<<endl;
for(int j=1;j<P.size();j++){
if(!same(P[j],P[j-1])){
num--;
unite(P[j],P[j-1]);
}
}
// cout<<"stat2"<<endl;
L+=4-2*chongbian;
}
S++;
cout<<num<<" "<<S<<" "<<L<<endl;
}
}
return 0;
}