bzoj 1453: [Wc]Dface双面棋盘

Posted Nico&11101001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",tree[1].s1,tree[1].s0);
    }
    return 0;
}

 

以上是关于bzoj 1453: [Wc]Dface双面棋盘的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1453: [Wc]Dface双面棋盘

bzoj1453: [Wc]Dface双面棋盘

1453: [Wc]Dface双面棋盘 (线段树+并茶几)

[Wc]Dface双面棋盘

[Wc]Dface双面棋盘()

bzoj 1453 双面棋盘