Description
Input
Output
Sample Input
Sample Output
HINT
Source
鸣谢刘汝佳先生授权使用
思路
线段树,树上的节点
[left,right]
表示
[left,right]
这些行,线段树存黑色区域的个数、白色区域的个数,以及左边界和右边界的情况。在合并时只要暴力枚举两区间的交接处,如果是同一种颜色而且不在同一并查集内,就将这两种颜色合并,同时相应的颜色个数减一。
代码
#include <cstdio>
const int maxn=500;
int map[maxn+10][maxn+10],n;
int tmp[(maxn<<2)+10];
struct data
{
int fa[(maxn<<2)+10],b,w,tot,left,right;
int find(int x)
{
if(fa[x]==x)
{
return x;
}
else
{
return fa[x]=find(fa[x]);
}
}
int init(int x)
{
b=w=0;
left=right=x;
for(register int i=1; i<=n; ++i)
{
fa[i]=i;
}
for(register int i=1; i<=n; ++i)
{
if((i==1)||(map[x][i-1]!=map[x][i]))
{
if(map[x][i])
{
++b;
}
else
{
++w;
}
}
else
{
fa[find(i)]=fa[find(i-1)];
}
}
for(register int i=1; i<=n; ++i)
{
fa[i+n]=fa[i];
}
return 0;
}
data operator +(data other)//合并两个区间
{
data res;
res.left=left;
res.right=other.right;
int mid=(res.left+res.right)>>1;
res.b=b+other.b;
res.w=w+other.w;
for(register int i=1; i<=n<<1; ++i)
{
res.fa[i]=fa[i];
}
for(register int i=1; i<=n<<1; ++i)
{
res.fa[i+(n<<1)]=other.fa[i]+(n<<1);
}
for(register int i=1; i<=n; ++i)
{
if(map[mid][i]==map[mid+1][i])
{
int x=res.find(i+n),y=res.find(i+(n<<1));
if(x!=y)
{
if(map[mid][i])
{
--res.b;
}
else
{
--res.w;
}
res.fa[x]=y;
}
}
}
for(register int i=1; i<=n<<2; ++i)
{
if(i<=n)
{
tmp[res.find(i)]=i;
}
if(i>n*3)
{
tmp[res.find(i)]=i-(n<<1);
}
}
for(register int i=1; i<=n; ++i)
{
res.fa[i]=tmp[res.fa[i]];
res.fa[i+n]=tmp[res.fa[i+n*3]];
}
return res;
}
};
struct segment_tree
{
data val[maxn+10];
int build(int now,int left,int right)
{
if(left==right)
{
val[now].init(left);
return 0;
}
int mid=(left+right)>>1;
build(now<<1,left,mid);
build(now<<1|1,mid+1,right);
val[now]=val[now<<1]+val[now<<1|1];
return 0;
}
int modify(int now,int left,int right,int pos)
{
if(left==right)
{
val[now].init(left);
return 0;
}
int mid=(left+right)>>1;
if(pos<=mid)
{
modify(now<<1,left,mid,pos);
}
else
{
modify(now<<1|1,mid+1,right,pos);
}
val[now]=val[now<<1]+val[now<<1|1];
return 0;
}
};
segment_tree st;
int m,a,b;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int main()
{
n=read();
for(register int i=1; i<=n; ++i)
{
for(register int j=1; j<=n; ++j)
{
map[i][j]=read();
}
}
st.build(1,1,n);
m=read();
while(m--)
{
a=read();
b=read();
map[a][b]=1-map[a][b];
st.modify(1,1,n,a);
printf("%d %d\n",st.val[1].b,st.val[1].w);
}
return 0;
}