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
",T[1].c[1],T[1].c[0]);
  return 0;
}

  

原文地址:https://www.cnblogs.com/clrs97/p/4403179.html