卧薪尝胆,厚积薄发。
      
    
            WC2005 双面棋盘
        
        
        Description:
给一个
$n\times n$
的棋盘,每次把一个格子的颜色反转,并询问黑色和白色格子的联通块数。
$1\leqslant n\leqslant 200,1\leqslant m\leqslant 10000$
Solution:
几乎是线段树分治
$+$
并查集的模板,每次讨论一下他和周围四个点的关系就行了。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cctype>
#include<cstring>
using namespace std;
#define re register
inline int rd()
{
    register int res = 0;
    register char c = getchar();
    while(!isdigit(c))c = getchar();
    while(isdigit(c))
    {
        res = (res << 1) + (res << 3) + c - '0';
        c = getchar();
    }
    return res;
}
int n,m;
#define MAXN 210
int col[MAXN][MAXN];
int tim[MAXN][MAXN];
int c[MAXN][MAXN];
int id(int x,int y){return n * (x - 1) + y;}
int x[MAXN * MAXN],y[MAXN * MAXN];
int cnt;
#define MAXM 10010
struct node
{
    int lc,rc;
    vector< pair<int,int> > v;
}t[MAXM << 1];
int ptr = 0;
int newnode(){return ++ptr;}
int root;
#define mid ((l + r) >> 1)
void build(int &rt,int l,int r)
{
    rt = newnode();
    if(l == r)return;
    build(t[rt].lc,l,mid);
    build(t[rt].rc,mid + 1,r);
    return;
}
void add(int rt,int L,int R,int x,int y,int l,int r)
{
    if(L > R)return;
    if(L <= l && r <= R)
    {
        t[rt].v.push_back(make_pair(x,y));
        return;
    }
    if(L <= mid)add(t[rt].lc,L,R,x,y,l,mid);
    if(R > mid)add(t[rt].rc,L,R,x,y,mid + 1,r);
    return;
}
int ans[MAXM][2];
#define fi first
#define se second
int mx[4] = {0,0,1,-1};
int my[4] = {1,-1,0,0};
struct UFS
{
    int f[MAXN * MAXN],rnk[MAXN * MAXN];
    int find(int x){return (x == f[x] ? x : find(f[x]));}
    int res1,res2;
    pair<int,int> stack[10000000];
    int top;
    void init()
    {
        for(re int i = 1;i <= n * n;++i)f[i] = i;
        return;
    }
    void merge(int a,int b)
    {
        re int p = find(a),q = find(b);
        if(p == q)return;
        if(c[x[a]][y[a]] == 0)--res1;
        else --res2;
        if(rnk[p] > rnk[q])swap(p,q);
        f[p] = q;stack[++top] = make_pair(2,p);
        if(rnk[p] == rnk[q])++rnk[q],stack[++top] = make_pair(3,q);
        return;
    }
    void insert(pair<int,int> k)
    {
        stack[++top] = make_pair(1,k.fi);
        c[x[k.fi]][y[k.fi]] = k.se;
        if(k.se == 0)++res1;
        else ++res2;
        for(re int i = 0;i < 4;++i)
        {
            re int nx = x[k.fi] + mx[i],ny = y[k.fi] + my[i];
            if(c[nx][ny] == -1)continue;
            if(c[nx][ny] != c[x[k.fi]][y[k.fi]])continue;
            merge(k.fi,id(nx,ny));
        }
        return;
    }
    void reset(int bot)
    {
        while(top > bot)
        {
            re pair<int,int> t = stack[top--];
            if(t.fi == 1)
            {
                if(c[x[t.se]][y[t.se]] == 0)--res1;
                else --res2;
                c[x[t.se]][y[t.se]] = -1;
            }
            if(t.fi == 2)
            {
                f[t.se] = t.se;
                if(c[x[t.se]][y[t.se]] == 0)++res1;
                else ++res2;
            }
            if(t.fi == 3)--rnk[t.se];
        }
        return;
    }
}s;
void dfs(int rt,int l,int r)
{
    re int st = s.top;
    for(re vector< pair<int,int> >::iterator it = t[rt].v.begin();it != t[rt].v.end();++it)s.insert(*it);
    if(l == r)
    {
    	ans[l][0] = s.res1;ans[l][1] = s.res2;
    	s.reset(st);
    	return;
    }
    dfs(t[rt].lc,l,mid);
    dfs(t[rt].rc,mid + 1,r);
    s.reset(st);
    return;
}
int main()
{
    scanf("%d",&n);
    for(re int i = 1;i <= n;++i)for(re int j = 1;j <= n;++j)col[i][j] = rd();
    cnt = n * n;
    for(re int i = 1;i <= n;++i)for(re int j = 1;j <= n;++j)tim[i][j] = 1;
    for(re int i = 1;i <= n;++i)for(re int j = 1;j <= n;++j)x[id(i,j)] = i,y[id(i,j)] = j;
    re int x,y;
    scanf("%d",&m);
    build(root,1,m);
    for(re int i = 1;i <= m;++i)
    {
    	x = rd();y = rd();
    	add(root,tim[x][y],i - 1,id(x,y),col[x][y],1,m);
    	col[x][y] ^= 1;tim[x][y] = i;
    }
    for(re int i = 1;i <= n;++i)
  		for(re int j = 1;j <= n;++j)
            add(root,tim[i][j],m,id(i,j),col[i][j],1,m);
    memset(c,-1,sizeof(c));
    s.init();
    dfs(root,1,m);
    for(re int i = 1;i <= m;++i)printf("%d %d\n",ans[i][1],ans[i][0]);
    return 0;
}
        Copyright © 2020
        
          wjh15101051
        
      
      ღゝ◡╹)ノ♡
    
          Date: Thu Jan 24 20:52:14 CST 2019
          
          In Category:
          
          In tag:
        
            Timeline
          
            About
          
            Toolbox
          
              Friends