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

来源:互联网 发布:手机淘宝怎么退出 编辑:程序博客网 时间:2024/06/06 10:01

题意:给了一个n*m的矩阵,上下左右相同数的点可以并为同一个联通块,对于每个询问L,R 输出(1,L) … (n,R)的块中有几个联通块。

1

#define MAXN 100010#define lson i<<1#define rson i<<1|1int 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);    }}
阅读全文
0 0
原创粉丝点击