线段树套并查集,怎么暴力怎么写。
#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; }