卧薪尝胆,厚积薄发。
WC2005 双面棋盘
Date: Thu Jan 24 20:52:14 CST 2019 In Category: NoCategory

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
ღゝ◡╹)ノ♡