设备塔
题目描述
为了封印辉之环,古代塞姆利亚大陆的人民在异空间中建造了一座设备塔。 简单的说,这座设备塔是一个漂浮在异空间中的圆柱体,圆柱体两头的圆是计算核心,而侧面则是 传输信息所用的数据通道,划分成 N ∗ m 个区块。 然而,随着工作的继续进行,他们希望把侧面的一部分区块也改造成其他模块。然而,任何时候都 必须保证存在一条数据通道,能从圆柱体的一端通向另一端。 由于无法使用辉之环掌控下的计算系统,他们寻求你的帮助来解决这个问题。他们将逐个输入想要 改造的区域,而你则执行所有可行的改造并忽略可能导致数据中断的改造。
输入
第一行,包含两个整数 N; M; K,表示侧面的长和宽,以及操作数。 接下来 K 行,每行包含三个整数 xi; yi,表示操作的区块的坐标。 数据保证不会对已经操作成功的区块进行操作。
输出
输出一行,表示有多少个操作可以被执行。
样例输入
3 4 9 2 2 3 2 2 3 3 4 3 1 1 3 2 1 1 1 1 4
样例输出
6
提示
对于分值为 30 的子任务 1,保证 N; M ≤ 100; K ≤ 5000。
对于分值为 30 的子任务 2,保证 N; M ≤ 3000; K ≤ 5000。
对于分值为 40 的子任务 3,保证 N; M ≤ 3000; K ≤ 300000。
对障碍的8联通性用并查集维护。
#include<bits/stdc++.h> #define ha(x,y) (x*(2*m+1)+y) using namespace std; int n,m,k,x,y,f[3011*6711],ll,rr,jj,ans,kk,qq; map<int,int> mp; bool usd[3011][6011]; int gf(int x){ return x^f[x]?f[x]=gf(f[x]):x; } signed main () { scanf("%d%d%d",&n,&m,&k); for (int i=ha(n,2*m);i;i--) f[i]=i; for (int i=1;i<=k;i++) { scanf("%d%d",&x,&y); // assert(!usd[x][y]); if (usd[x][y]) continue; mp.clear(); kk=0; for (int p=x-1;p<=x+1;p++) for (int q=y-1;q<=y+1;q++) { qq=q; if (q==0) {qq=2*m;} if (q>2*m) {qq-=2*m;} if (!usd[p][qq]) continue; if (p==x&&qq==y) continue; jj=gf(f[ha(p,qq)]); mp[jj]=1; // ll=min(l[jj],ll); rr=max(r[jj],rr); } for (int p=x-1;p<=x+1;p++) for (int q=y+m-1;q<=y+m+1;q++) { qq=q; if (q==0) {qq=2*m;} if (q>2*m) {qq-=2*m;} if (!usd[p][qq]) continue; if (p==x&&qq==y+m) continue; // cerr<<ha(p,q)<<endl; jj=gf(f[ha(p,qq)]); if (mp[jj]==1) kk=1; // ll=min(l[jj],ll); rr=max(r[jj],rr); } if (kk) continue; ans++; usd[x][y]=1; usd[x][y+m]=1; for (int p=x-1;p<=x+1;p++) for (int q=y-1;q<=y+1;q++) { qq=q; if (q==0) {qq=2*m;} if (q>2*m) {qq-=2*m;} if (!usd[p][qq]) continue; if (p==x&&qq==y) continue; jj=gf(f[ha(p,qq)]); f[jj]=ha(x,y); } for (int p=x-1;p<=x+1;p++) for (int q=y+m-1;q<=y+m+1;q++) { qq=q; if (q==0) {qq=2*m;} if (q>2*m) {qq-=2*m;} if (!usd[p][qq]) continue; if (p==x&&qq==y+m) continue; jj=gf(f[ha(p,qq)]); f[jj]=ha(x,y+m); } } printf("%d\n",ans); return 0; }