BZOJ1453: [Wc]Dface双面棋盘

Description

Input

Output

Sample Input


Sample Output


HINT

线段树套并查集应该是比较好写的做法,时间复杂度为O(N^3+M*NlogN)。
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=210;
int n,A[maxn][maxn];
struct Node {
    int res[2],pa[maxn*2];
    int findset(int x) {return pa[x]==x?x:findset(pa[x]);}
    void init(int x) {
        res[0]=res[1]=0;
        rep(i,1,n) pa[i]=i;
        rep(i,1,n) {
            res[!A[x][i]]++;
            if(i>1&&A[x][i-1]==A[x][i]) res[!A[x][i]]--,pa[findset(i-1)]=findset(i);
        }
        rep(i,1,n) pa[i+n]=pa[i];
    }
}T[maxn<<2];
int pa[maxn*4],tmp[maxn*4];
int findset(int x) {return x==pa[x]?x:pa[x]=findset(pa[x]);}
void maintain(int o,int mid) {
    int lc=o<<1,rc=lc|1;
    T[o].res[0]=T[lc].res[0]+T[rc].res[0];
    T[o].res[1]=T[lc].res[1]+T[rc].res[1];
    rep(i,1,n*2) pa[i]=T[lc].pa[i];
    rep(i,1,n*2) pa[i+2*n]=T[rc].pa[i]+2*n;
    rep(i,1,n) if(A[mid][i]==A[mid+1][i]) {
        int x=findset(i+n),y=findset(i+2*n);
        if(x!=y) {
            T[o].res[!A[mid][i]]--;
            pa[x]=y;
        }
    }
    rep(i,1,n*4) {
        if(i<=n) tmp[findset(i)]=i;
        if(i>3*n) tmp[findset(i)]=i-2*n;
    }
    rep(i,1,n) T[o].pa[i]=tmp[pa[i]];
    rep(i,1,n) T[o].pa[i+n]=tmp[pa[i+3*n]];
}
void build(int o,int l,int r) {
    if(l==r) T[o].init(l);
    else {
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        build(lc,l,mid);build(rc,mid+1,r);
        maintain(o,mid);
    }
}
void update(int o,int l,int r,int p) {
    if(l==r) T[o].init(l);
    else {
        int mid=l+r>>1,lc=o<<1,rc=lc|1;
        if(p<=mid) update(lc,l,mid,p);
        else update(rc,mid+1,r,p);
        maintain(o,mid);
    }
}
int main() {
    n=read();
    rep(i,1,n) rep(j,1,n) A[i][j]=read();
    build(1,1,n);
    dwn(i,read(),1) {
        int x=read(),y=read();A[x][y]^=1;
        update(1,1,n,x);
        printf("%d %d
",T[1].res[0],T[1].res[1]);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5547135.html