• bzoj 1453: [Wc]Dface双面棋盘


    1453: [Wc]Dface双面棋盘

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 617  Solved: 317
    [Submit][Status][Discuss]

    Description

    Input

    Output

    Sample Input


    Sample Output


    HINT

     
     
     
    用线段树+数组模拟并查集,维护每一列的连通性,然后暴力合并就行了,常数巨大
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 210
    int father[N<<2],tmp[N<<2],n,m,a[N][N];
    struct Node{
        int l,r;
        int le[N],ri[N];
        int lb[N],rb[N];
        int s0,s1;
    }tree[N<<2];
    
    inline int find(int x){
        if(father[x]!=x)father[x]=find(father[x]);
        return father[x];
    }
    void update(int rt){
        tree[rt].s0=tree[rt<<1].s0+tree[rt<<1|1].s0;
        tree[rt].s1=tree[rt<<1].s1+tree[rt<<1|1].s1;
        memcpy(tree[rt].lb,tree[rt<<1].lb,sizeof tree[rt].lb);
        memcpy(tree[rt].rb,tree[rt<<1|1].rb,sizeof tree[rt].rb);
        for(int i=1;i<=n<<2;i++) father[i]=i;
        for(int i=1;i<=n;i++) tree[rt<<1|1].le[i]+=2*n,tree[rt<<1|1].ri[i]+=2*n;
        for(int i=1;i<=n;i++){
            int x=tree[rt<<1].ri[i],y=tree[rt<<1|1].le[i];
            if(find(x)!=find(y)&&tree[rt<<1].rb[i]==tree[rt<<1|1].lb[i]){
                father[find(x)]=find(y);
                if(tree[rt<<1].rb[i]){
                    tree[rt].s1--;
                }else{
                    tree[rt].s0--;
                }
            }
        }
        for(int i=1;i<=n;i++) tree[rt].le[i]=find(tree[rt<<1].le[i]),
        tree[rt].ri[i]=find(tree[rt<<1|1].ri[i]);
        for(int i=1;i<=n;i++) tmp[i<<1]=tree[rt].le[i],tmp[(i<<1)-1]=tree[rt].ri[i];
        sort(tmp+1,tmp+1+2*n);
        int mxdata=unique(tmp+1,tmp+1+2*n)-tmp-1;
        for(int i=1;i<=n;i++) tree[rt].le[i]=lower_bound(tmp+1,tmp+1+mxdata,
        tree[rt].le[i])-tmp,tree[rt].ri[i]=lower_bound(tmp+1,tmp+1+mxdata,tree[rt].ri[i])-tmp;
        for(int i=1;i<=n;i++) tree[rt<<1|1].le[i]-=2*n,tree[rt<<1|1].ri[i]-=2*n;
    }
    
    void build(int l,int r,int rt){
        tree[rt].l=l;tree[rt].r=r;
        if(l==r){
            int tot=0;
            for(int i=1;i<=n;i++)
            {
                if(a[i][l]!=a[i-1][l])
                {
                    tot++;
                    if(a[i][l]) tree[rt].s1++;
                    else tree[rt].s0++;
                }
                tree[rt].le[i]=tree[rt].ri[i]=tot;
                tree[rt].lb[i]=tree[rt].rb[i]=a[i][l];
            }
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        update(rt);
    }
    
    void modify(int rt,int pos)
    {
        if(tree[rt].l==tree[rt].r)
        {
            int tot=0;tree[rt].s1=0;tree[rt].s0=0;
            for(int i=1;i<=n;i++)
            {
                if(a[i][pos]!=a[i-1][pos])
                {
                    tot++;
                    if(a[i][pos]) tree[rt].s1++;
                    else tree[rt].s0++;
                }
                tree[rt].le[i]=tree[rt].ri[i]=tot;
                tree[rt].lb[i]=tree[rt].rb[i]=a[i][pos];
            }
            return;
        }
        int mid=(tree[rt].l+tree[rt].r)>>1;
        if(pos<=mid) modify(rt<<1,pos);
        else modify(rt<<1|1,pos);
        update(rt);
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            a[0][i]=-1;
            for(int j=1;j<=n;j++){
                scanf("%d",&a[i][j]);
            }
        }
        build(1,n,1);
        scanf("%d",&m);
        while(m--){
            int x,y;
            scanf("%d%d",&x,&y);
            a[x][y]^=1;
            modify(1,y);
            printf("%d %d
    ",tree[1].s1,tree[1].s0);
        }
        return 0;
    }
  • 相关阅读:
    angularjs学习笔记—工具方法
    js日期格式转换的相关问题探讨
    vue路由原理剖析
    如何减少UI设计师产品与前端工程师的沟通成本
    前端优化带来的思考,浅谈前端工程化
    前端入门方法
    自写juqery插件实现左右循环滚动效果图
    前端大综合
    前端收集
    如何在代码中减少if else语句的使用
  • 原文地址:https://www.cnblogs.com/sssy/p/7324162.html
Copyright © 2020-2023  润新知