岛屿

总时间限制:40000ms单个测试点时间限制:4000ms内存限制:128000kB
描述

从前有一座岛屿,这座岛屿是一个长方形,被划为N*M的方格区域,每个区域都有一个确定的高度。不幸的是海平面开始上涨,在第i年,海平面的高度为t[i]。如果一个区域的高度小于等于海平面高度,则视为被淹没。那些没有被淹没的连通的区域够成一个连通块。现在问第i年,这样的连通块有多少个。

    例如:第一年海平面高度为1,有2个连通块。

                      第二年海平面高度为2,有3个连通块。

 

输入
第一行包含两个数N,M。
接下来是一个N*M的矩阵,第i行第j列表示这个格子的高度h[i][j]
接下来是一个数T,表示有T天,
最后一行有T个数,第i个数表示第i天的水位高度。(保证是递增的)
输出
输出包含一行T个数,第i个数表示第i天的连通块个数。
样例输入
4 5
1 2 3 3 1
1 3 2 2 1
2 1 3 4 3
1 2 2 2 2
5
1 2 3 4 5
样例输出
2 3 1 0 0
提示
对于50%的数据: 1 <= n*m <= 1000, 1<= T <=3000
对于100%的数据:1<= n <= 3000 , 1<= m <= 3000 , 1<=T<=100000
1<= h[i][j] <=10^9

思路

并查集;
倒序。。。然后问题迎刃而解。

代码实现

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=3e3+10;
 5 const int maxq=1e5+10;
 6 int n,m,t,now;
 7 int a,b;
 8 int q[maxq],ans[maxq];
 9 int f[maxn*maxn];
10 int hb[]={1,-1,0,0};
11 int lb[]={0,0,1,-1};
12 struct point{int x,y,h;}p[maxn*maxn];
13 int find_f(int k){return f[k]==k?k:f[k]=find_f(f[k]);}
14 bool comp(const point&a,const point&b){return a.h>b.h;}
15 int main(){
16     scanf("%d%d",&n,&m);
17     for(int i=1;i<=n;i++)
18     for(int j=1;j<=m;j++){
19         int k=(i-1)*m+j;
20         scanf("%d",&p[k].h);
21         p[k].x=i,p[k].y=j;
22     }
23     sort(p+1,p+n*m+1,comp);
24     scanf("%d",&t);
25     for(int i=1;i<=t;i++) scanf("%d",&q[i]);
26     int j=1;
27     for(int i=t;i>0;i--){
28         for(j;j<=n*m&&p[j].h>q[i];j++){
29             int h=p[j].x,l=p[j].y;
30             a=(h-1)*m+l,f[a]=a,now++;
31             for(int k=0;k<4;k++){
32                 int nh=h+hb[k],nl=l+lb[k];
33                 b=(nh-1)*m+nl,a=find_f(f[a]),b=find_f(f[b]);
34                 if(nh&&nl&&nh<=n&&nl<=m&&f[b]&&f[a]!=f[b]) f[b]=a,now--;
35             }
36         }
37         ans[i]=now;
38     }
39     for(int i=1;i<t;i++) printf("%d ",ans[i]);
40     printf("%d\n",ans[t]);
41     return 0;
42 }

 

posted @ 2017-07-20 06:59  J_william  阅读(443)  评论(0编辑  收藏  举报