题目
r*c(0<r,c<=1e9)的网格图,有n(0<=n<=200)个障碍点不能被访问,其余点是连通的,
输出这张网格图上的连通块的数量,按增序输出每个连通块的大小
思路来源
归神+涛神
题解
二维离散化裸题
之前一直刻意避着不做,今天终于2h Debug啃过去了
实际的过程和excel里把空白行缩了的过程是一样的……
比如对于左图,就可以缩成三行三列,让中间变成一个点,如右图所示
缩的点记录一下实际代表的水平方向的[l,r]和竖直方向的[l,r],访问这个空白点的时候加一下面积就好了
于是1e9*1e9的图被缩成最大400*400的图,考虑200个点占200个行和列,每两个行和列之间各有一个空白的特殊情形
分别对一维进行离散化,然后二维点就是两个一维的构成的点对
一维离散化的时候,考虑读入的增序排列的已经去重的yi,
①如果左边还有空白区域,应将
加入;
②如果右边还有空白区域,应将
加入
这样不如就直接在排序之前把1和c直接加进y[]数组,就不用特判了
把每个yi离散化成一个的列,两个列之间离散化出一条实际代表
的列
剩余的就是在一个离散化的图上dfs的操作了
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
const int maxn=450;
typedef long long ll;
struct vertex
{
ll x,y;
vertex(){}
}e[maxn];
struct node
{
ll l,r;
node(){}
node(ll L,ll R):l(L),r(R){}
}xx[maxn],yy[maxn];
int t,n,r,c;
ll x[maxn],y[maxn];
int cnt[2],num[2];
map<ll,ll>toX,toY;
bool vis[maxn][maxn];
ll res[maxn],ans,tmp;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
bool ok(int x,int y)
{
return x>=0&&x<num[0]&&y>=0&&y<num[1]&&!vis[x][y];
}
void dfs(int x,int y)
{
vis[x][y]=1;
tmp+=(xx[x].r-xx[x].l+1)*(yy[y].r-yy[y].l+1);
for(int i=0;i<4;++i)
{
int xx=x+dx[i],yy=y+dy[i];
if(ok(xx,yy))dfs(xx,yy);
}
}
void debug()
{
for(int i=0;i<num[0];++i)
{
for(int j=0;j<num[1];++j)
printf("%4d ",vis[i][j]);
puts("");
}
}
void init()
{
memset(vis,0,sizeof vis);
memset(x,0,sizeof x);
memset(y,0,sizeof y);
num[0]=num[1]=0;
ans=0;
toX.clear();
toY.clear();
}
int main()
{
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
init();
scanf("%d%d",&r,&c);
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%lld%lld",&e[i].x,&e[i].y);
x[i]=e[i].x;y[i]=e[i].y;
}
x[n+1]=1;x[n+2]=r;
y[n+1]=1;y[n+2]=c;
sort(x+1,x+n+3);
sort(y+1,y+n+3);
cnt[0]=unique(x+1,x+n+3)-(x+1);
cnt[1]=unique(y+1,y+n+3)-(y+1);
xx[num[0]]=node(x[1],x[1]);
toX[x[1]]=num[0]++;
for(int i=2;i<=cnt[0];++i)
{
if(x[i-1]+1<=x[i]-1)xx[num[0]++]=node(x[i-1]+1,x[i]-1);
xx[num[0]]=node(x[i],x[i]);
toX[x[i]]=num[0]++;
}
yy[num[1]]=node(y[1],y[1]);
toY[y[1]]=num[1]++;
for(int i=2;i<=cnt[1];++i)
{
if(y[i-1]+1<=y[i]-1)yy[num[1]++]=node(y[i-1]+1,y[i]-1);
yy[num[1]]=node(y[i],y[i]);
toY[y[i]]=num[1]++;
}
//for(int i=0;i<num[0];++i)
//printf("x%d:(%d,%d)\n",i,xx[i].l,xx[i].r);
//for(int i=0;i<num[1];++i)
//printf("y%d:(%d,%d)\n",i,yy[i].l,yy[i].r);
for(int i=1;i<=n;++i)
{
e[i].x=toX[e[i].x];
e[i].y=toY[e[i].y];
//printf("[%d,%d]\n",e[i].x,e[i].y);
vis[e[i].x][e[i].y]=1;
}
//debug();
for(int i=0;i<num[0];++i)
{
for(int j=0;j<num[1];++j)
{
if(ok(i,j))
{
tmp=0;
dfs(i,j);
res[++ans]=tmp;
}
}
}
printf("Case #%d:\n",cas);
printf("%lld\n",ans);
if(ans)
{
sort(res+1,res+ans+1);
for(int i=1;i<=ans;++i)
printf("%lld%c",res[i],i==ans?'\n':' ');
}
}
return 0;
}