Codeforces 811E Vladik and Entertaining Flags [线段树][并查集]

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

题意:给了一个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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值