题目
并查集中的 1.. n 1..n 1..n表示上方, n + 1..2 n n+1..2n n+1..2n表示下方,合并时 2 n + 1..4 n 2n+1..4n 2n+1..4n用于右侧的上下方并查集

#include<bits/stdc++.h>
using namespace std;
const int N=502;
#define mid (l+r>>1)
int mp[N<<2],a[N][N],n,m,x,y,i,j;
struct bing{
    int f[N<<2];
    void init(int n){for (int i=1;i<=n;i++) f[i]=i;}
    int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
    void merge(int x,int y){f[find(x)]=find(y);}
    bool same(int x,int y){return find(x)==find(y);}
};
struct seg{
    struct node{
        int b,w;
        bing U;
    }t[N<<2];
    void maintain(int rt,int l,int r){
        t[rt].b=t[rt<<1].b+t[rt<<1|1].b;
        t[rt].w=t[rt<<1].w+t[rt<<1|1].w;
        t[rt].U.init(n<<2);
        for (int i=1;i<=n<<1;i++){
            t[rt].U.merge(i,t[rt<<1].U.find(i));
            t[rt].U.merge(i+(n<<1),t[rt<<1|1].U.find(i)+(n<<1));
        }
        for (int i=1;i<=n;i++)
            if (a[mid][i]==a[mid+1][i]){
                if (t[rt].U.same(i+n,i+(n<<1))) continue;
                t[rt].U.merge(i+n,i+(n<<1));
                t[rt].w-=a[mid][i]==0;
                t[rt].b-=a[mid][i]==1;
            }
        for (int i=1;i<=n<<2;i++) t[rt].U.find(i);
        memset(mp,0,sizeof(mp));
        for (int i=1;i<=n;i++)
            if (!mp[t[rt].U.f[i]]) mp[t[rt].U.f[i]]=i,t[rt].U.f[i]=i;
            else t[rt].U.f[i]=mp[t[rt].U.f[i]];
        for (int i=n*3+1;i<=n<<2;i++){
            if (!mp[t[rt].U.f[i]]) mp[t[rt].U.f[i]]=i-(n<<1),t[rt].U.f[i]=i-(n<<1);
            else t[rt].U.f[i]=mp[t[rt].U.f[i]];
        }
        for (int i=1;i<=n;i++) t[rt].U.f[i+n]=t[rt].U.f[i+n*3];
        for (int i=n<<1|1;i<=n<<2;i++) t[rt].U.f[i]=i;
    }
    void make(int rt,int l){
        t[rt].U.init(n<<2);
        t[rt].w=a[l][1]==0;
        t[rt].b=a[l][1]==1;
        t[rt].U.merge(1+n,1);
        for (int i=2;i<=n;i++){
            t[rt].U.merge(i+n,i);
            if (a[l][i]==a[l][i-1]) t[rt].U.merge(i,i-1);
            else t[rt].b+=a[l][i]==1,t[rt].w+=a[l][i]==0;
        }
    }
    void build(int rt,int l,int r){
        if (l==r){
            make(rt,l);
            return;
        }
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
        maintain(rt,l,r);
    }
    void change(int rt,int l,int r,int pos){
        if (l==r){
            make(rt,l);
            return;
        }
        if (pos<=mid) change(rt<<1,l,mid,pos);
        else change(rt<<1|1,mid+1,r,pos);
        maintain(rt,l,r);
    }
}T;
int main(){
    scanf("%d",&n);
    for (i=1;i<=n;i++)
        for (j=1;j<=n;j++) scanf("%d",&a[i][j]);
    T.build(1,1,n);
    scanf("%d",&m);
    while (m--){
        scanf("%d%d",&x,&y);
        a[x][y]^=1;
        T.change(1,1,n,x);
        printf("%d %d\n",T.t[1].b,T.t[1].w);
    }
}