[Wc]Dface双面棋盘

来源:互联网 发布:小公司网络需求调查表 编辑:程序博客网 时间:2024/05/11 10:08

Description
Description

Input
Input

Output
Output

Sample Input
Sample Input

Sample Output
Sample Output

HINT
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;}