BZOJ1453 : [Wc]Dface双面棋盘

线段树套并查集,怎么暴力怎么写。

 

#include<cstdio>

#define N 202

struct P{int c[2],f[N*2];}T[N*4];

int n,m,i,j,a[N][N],f[N*4],t[N*4];

int F(int x){return f[x]==x?x:f[x]=F(f[x]);}

inline void cal(int x,int p){

  int i,j=1;

  T[x].c[a[p][1]]=1,T[x].c[a[p][1]^1]=0,T[x].f[1]=T[x].f[1+n]=1;

  for(i=2;i<=n;i++){

    if(a[p][i]!=a[p][j])T[x].c[a[p][j=i]]++;

    T[x].f[i]=T[x].f[i+n]=j;

  }

}

inline void up(int x,int p){

  int l=x<<1,r=x<<1|1,i;

  for(i=0;i<2;i++)T[x].c[i]=T[l].c[i]+T[r].c[i];

  for(i=1;i<=n*2;i++)f[i]=T[l].f[i];

  for(i=1;i<=n*2;i++)f[i+n*2]=T[r].f[i]+n*2;

  for(i=1;i<=n;i++)if(a[p][i]==a[p+1][i]&&F(i+n)!=F(i+n*2))T[x].c[a[p][i]]--,f[f[i+n]]=f[i+n*2];

  for(i=1;i<=n*4;i++){

    f[i]=F(i);

    if(i<=n)t[f[i]]=i;

    if(i>n*3)t[f[i]]=i-n*2;

  }

  for(i=1;i<=n;i++)T[x].f[i]=t[f[i]];

  for(i=1;i<=n;i++)T[x].f[i+n]=t[f[i+n*3]];

}

void build(int x,int a,int b){

  if(a==b){cal(x,a);return;}

  int mid=(a+b)>>1;

  build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x,mid);

}

void change(int x,int a,int b,int c){

  if(a==b){cal(x,a);return;}

  int mid=(a+b)>>1;

  if(c<=mid)change(x<<1,a,mid,c);else change(x<<1|1,mid+1,b,c);

  up(x,mid);

}

int main(){

  scanf("%d",&n);

  for(i=1;i<=n;i++)for(j=1;j<=n;j++)scanf("%d",&a[i][j]);

  build(1,1,n);

  scanf("%d",&m);

  while(m--)scanf("%d%d",&i,&j),a[i][j]^=1,change(1,1,n,i),printf("%d %d\n",T[1].c[1],T[1].c[0]);

  return 0;

}

  

 

你可能感兴趣的:(ZOJ)