BZOJ1453: [Wc]Dface双面棋盘
Description
Input
Output
Sample Input
Sample Output
HINT
线段树套并查集应该是比较好写的做法,时间复杂度为O(N^3+M*NlogN)。
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=210; int n,A[maxn][maxn]; struct Node { int res[2],pa[maxn*2]; int findset(int x) {return pa[x]==x?x:findset(pa[x]);} void init(int x) { res[0]=res[1]=0; rep(i,1,n) pa[i]=i; rep(i,1,n) { res[!A[x][i]]++; if(i>1&&A[x][i-1]==A[x][i]) res[!A[x][i]]--,pa[findset(i-1)]=findset(i); } rep(i,1,n) pa[i+n]=pa[i]; } }T[maxn<<2]; int pa[maxn*4],tmp[maxn*4]; int findset(int x) {return x==pa[x]?x:pa[x]=findset(pa[x]);} void maintain(int o,int mid) { int lc=o<<1,rc=lc|1; T[o].res[0]=T[lc].res[0]+T[rc].res[0]; T[o].res[1]=T[lc].res[1]+T[rc].res[1]; rep(i,1,n*2) pa[i]=T[lc].pa[i]; rep(i,1,n*2) pa[i+2*n]=T[rc].pa[i]+2*n; rep(i,1,n) if(A[mid][i]==A[mid+1][i]) { int x=findset(i+n),y=findset(i+2*n); if(x!=y) { T[o].res[!A[mid][i]]--; pa[x]=y; } } rep(i,1,n*4) { if(i<=n) tmp[findset(i)]=i; if(i>3*n) tmp[findset(i)]=i-2*n; } rep(i,1,n) T[o].pa[i]=tmp[pa[i]]; rep(i,1,n) T[o].pa[i+n]=tmp[pa[i+3*n]]; } void build(int o,int l,int r) { if(l==r) T[o].init(l); else { int mid=l+r>>1,lc=o<<1,rc=lc|1; build(lc,l,mid);build(rc,mid+1,r); maintain(o,mid); } } void update(int o,int l,int r,int p) { if(l==r) T[o].init(l); else { int mid=l+r>>1,lc=o<<1,rc=lc|1; if(p<=mid) update(lc,l,mid,p); else update(rc,mid+1,r,p); maintain(o,mid); } } int main() { n=read(); rep(i,1,n) rep(j,1,n) A[i][j]=read(); build(1,1,n); dwn(i,read(),1) { int x=read(),y=read();A[x][y]^=1; update(1,1,n,x); printf("%d %d\n",T[1].res[0],T[1].res[1]); } return 0; }