[WC2005]雙面棋盤(線段樹+並查集)
阿新 • • 發佈:2019-01-06
線段樹+並查集維護連通性。
好像 \(700ms\) 的時限把我的常數超級大的做法卡掉了, 必須要開 \(O_2\) 才行。
對於線段樹的每一個結點都開左邊的並查集,右邊的並查集,然後合併。
\(Code\ Below:\)
#include <bits/stdc++.h> #define lson (rt<<1) #define rson (rt<<1|1) using namespace std; const int maxn=200+10; int n,m,a[maxn][maxn],f[maxn<<2],tmp[maxn<<2],wsum[maxn<<2],bsum[maxn<<2],lfa[maxn<<2][maxn],rfa[maxn<<2][maxn]; inline int read(){ register int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return (f==1)?x:-x; } int find(int x,int *f){ return (x==f[x])?x:f[x]=find(f[x],f); } inline void pushup(int rt,int mid){ wsum[rt]=wsum[lson]+wsum[rson]; bsum[rt]=bsum[lson]+bsum[rson]; for(int i=1;i<=n;i++){ f[i]=lfa[lson][i];f[i+n]=rfa[lson][i]; f[i+2*n]=lfa[rson][i]+2*n;f[i+3*n]=rfa[rson][i]+2*n; } for(int i=1;i<=n;i++) if(a[mid][i]==a[mid+1][i]){ if(find(i+n,f)!=find(i+2*n,f)){ f[find(i+n,f)]=f[find(i+2*n,f)]; if(a[mid][i]==0) wsum[rt]--; else bsum[rt]--; } } for(int i=1;i<=n;i++) tmp[find(i,f)]=i; for(int i=3*n+1;i<=4*n;i++) tmp[find(i,f)]=i-2*n; for(int i=1;i<=n;i++){ lfa[rt][i]=tmp[find(i,f)]; rfa[rt][i]=tmp[find(i+3*n,f)]; } } void build(int l,int r,int rt){ if(l == r){ for(int i=1;i<=n;i++) lfa[rt][i]=i; for(int i=1;i<=n;i++){ if(a[l][i]==0) wsum[rt]++; else bsum[rt]++; if(a[l][i-1]==a[l][i]){ lfa[rt][find(i-1,lfa[rt])]=i; if(a[l][i]==0) wsum[rt]--; else bsum[rt]--; } rfa[rt][i]=lfa[rt][i]; } return ; } int mid=(l+r)>>1; build(l,mid,lson); build(mid+1,r,rson); pushup(rt,mid); } void modify(int x,int l,int r,int rt){ if(l == r){ wsum[rt]=bsum[rt]=0; for(int i=1;i<=n;i++) lfa[rt][i]=i; for(int i=1;i<=n;i++){ if(a[l][i]==0) wsum[rt]++; else bsum[rt]++; if(a[l][i-1]==a[l][i]){ lfa[rt][find(i-1,lfa[rt])]=i; if(a[l][i]==0) wsum[rt]--; else bsum[rt]--; } rfa[rt][i]=lfa[rt][i]; } return ; } int mid=(l+r)>>1; if(x <= mid) modify(x,l,mid,lson); else modify(x,mid+1,r,rson); pushup(rt,mid); } int main() { n=read(); for(int i=1;i<=n;i++) a[i][0]=-1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=read(); build(1,n,1); m=read(); int x,y; while(m--){ x=read(),y=read(); a[x][y]^=1;modify(x,1,n,1); printf("%d %d\n",bsum[1],wsum[1]); } return 0; }