题意:给了一个n*m的矩阵,上下左右相同数的点可以并为同一个联通块,对于每个询问L,R 输出(1,L) … (n,R)的块中有几个联通块。
1
#define MAXN 100010
#define lson i<<1
#define rson i<<1|1
int n,m,q;
struct Node{
int ls[11],rs[11],sum;
}tree[N<<2];
int fa[N*10];
int mp[11][N];
int tot;
int Find(int x){ return x==fa[x]?x:fa[x]=Find(fa[x]); }
Node pushup(Node a,Node b,int mid){
Node ret;
ret.sum=a.sum+b.sum;
for(int i=1;i<=n;++i){
fa[a.ls[i]]=a.ls[i]; fa[a.rs[i]]=a.rs[i];
fa[b.ls[i]]=b.ls[i]; fa[b.rs[i]]=b.rs[i];
}
for(int i=1;i<=n;++i)if(mp[i][mid]==mp[i][mid+1]){
if(Find(a.rs[i])!=Find(b.ls[i])){
ret.sum--;int fx=Find(a.rs[i]);int fy=Find(b.ls[i]);
fa[fx]=fy;
}
}
for(int i=1;i<=n;++i){
ret.ls[i]=Find(a.ls[i]);
ret.rs[i]=Find(b.rs[i]);
}
return ret;
}
void build(int l,int r,int i){
if(l==r){
for(int j=1;j<=n;++j){
if(mp[j][l]==mp[j-1][l])tree[i].ls[j]=tree[i].rs[j]=tree[i].rs[j-1];
else tree[i].ls[j]=tree[i].rs[j]=++tot,tree[i].sum++;
}
return ;
}
int mid=(l+r)>>1;
build(l,mid,i<<1); build(mid+1,r,i<<1|1);
tree[i]=pushup(tree[i<<1],tree[i<<1|1],mid);
}
Node query(int ll,int rr,int i,int l,int r){
if(l<=ll&&rr<=r){
return tree[i];
}
int mid=(ll+rr)>>1;
if(r<=mid)return query(ll,mid,lson,l,r);
else if(l>mid)return query(mid+1,rr,rson,l,r);
else{
return pushup(query(ll,mid,lson,l,mid),query(mid+1,rr,rson,mid+1,r),mid);
}
}
int main(){
//freopen("in.txt","r",stdin);
sf("%d%d%d",&n,&m,&q);
tot=0;
rep(i,1,n){ rep(j,1,m){ sf("%d",&mp[i][j]); } }
build(1,m,1);
rep(i,1,q){
int l,r;sf("%d%d",&l,&r);
Node ans=query(1,m,1,l,r);
pf("%d\n",ans.sum);
}
}

本文介绍了一种针对矩阵中联通块进行高效查询的算法实现。该算法能够在给定的n*m矩阵上,通过构建特殊的数据结构来快速回答区间内有多少个独立的联通块。文章详细展示了算法的具体实现过程,包括节点定义、查找、合并操作及树状结构的建立和查询等关键步骤。
947

被折叠的 条评论
为什么被折叠?



