从前有一座岛屿,这座岛屿是一个长方形,被划为N*M的方格区域,每个区域都有一个确定的高度。不幸的是海平面开始上涨,在第i年,海平面的高度为t[i]。如果一个区域的高度小于等于海平面高度,则视为被淹没。那些没有被淹没的连通的区域够成一个连通块。现在问第i年,这样的连通块有多少个。
例如:第一年海平面高度为1,有2个连通块。
第二年海平面高度为2,有3个连通块。
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
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 int t[100010],ans[100010],f[9000010],n,m,tot,si; 7 struct node{ 8 int x,y,high; 9 }a[9000010]; 10 bool vis[9000010]; 11 int cmp(node i,node j){return i.high>j.high;} 12 int dx[]={0,0,1,-1}; 13 int dy[]={-1,1,0,0}; 14 int find(int x){ 15 if(x==f[x]) return x; 16 else return f[x]=find(f[x]); 17 } 18 void solve(){ 19 int sum=0,pos=1; 20 sort(a+1,a+tot+1,cmp); 21 for(int p=si;p>=1;p--){ 22 for(int i=pos;i<=tot;i++){ 23 int h=a[i].high,x=a[i].x,y=a[i].y; 24 if(h<=t[p]){ pos=i;break; } 25 if(h>t[p]&&!vis[(x-1)*m+y]) { 26 sum++;vis[(x-1)*m+y]=true; 27 for(int j=0;j<4;j++){ 28 int nx=x+dx[j],ny=y+dy[j]; 29 int k1=find((nx-1)*m+ny), 30 k2=find((x-1)*m+y); 31 if(nx>0&&nx<=n&&ny>0&&ny<=m 32 &&vis[k1]&&k1!=k2){ 33 sum--;f[k1]=k2; 34 } 35 } 36 } 37 } 38 ans[p]=sum; 39 } 40 for(int i=1;i<=si;i++) printf("%d ",ans[i]); 41 } 42 int main() 43 { 44 scanf("%d%d",&n,&m); 45 for(int i=1;i<=n;i++) 46 for(int j=1;j<=m;j++){ 47 scanf("%d",&a[++tot].high); 48 a[tot].x=i;a[tot].y=j; 49 } 50 for(int i=1;i<=tot;i++) f[i]=i; 51 scanf("%d",&si); 52 for(int i=1;i<=si;i++) scanf("%d",&t[i]); 53 solve(); 54 return 0; 55 }
神一样的倒序并查集。。。。
OpenJudge 东方14ACM小组 / 20170123 02 岛屿
原文:http://www.cnblogs.com/suishiguang/p/6344791.html