岛屿
- 总时间限制: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 }