bzoj 1453: [Wc]Dface双面棋盘
1453: [Wc]Dface双面棋盘
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 617 Solved: 317
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
![](http://www.lydsy.com/JudgeOnline/images/1453_4.jpg)
Sample Output
![](http://www.lydsy.com/JudgeOnline/images/1453_5.jpg)
HINT
用线段树+数组模拟并查集,维护每一列的连通性,然后暴力合并就行了,常数巨大
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 210 int father[N<<2],tmp[N<<2],n,m,a[N][N]; struct Node{ int l,r; int le[N],ri[N]; int lb[N],rb[N]; int s0,s1; }tree[N<<2]; inline int find(int x){ if(father[x]!=x)father[x]=find(father[x]); return father[x]; } void update(int rt){ tree[rt].s0=tree[rt<<1].s0+tree[rt<<1|1].s0; tree[rt].s1=tree[rt<<1].s1+tree[rt<<1|1].s1; memcpy(tree[rt].lb,tree[rt<<1].lb,sizeof tree[rt].lb); memcpy(tree[rt].rb,tree[rt<<1|1].rb,sizeof tree[rt].rb); for(int i=1;i<=n<<2;i++) father[i]=i; for(int i=1;i<=n;i++) tree[rt<<1|1].le[i]+=2*n,tree[rt<<1|1].ri[i]+=2*n; for(int i=1;i<=n;i++){ int x=tree[rt<<1].ri[i],y=tree[rt<<1|1].le[i]; if(find(x)!=find(y)&&tree[rt<<1].rb[i]==tree[rt<<1|1].lb[i]){ father[find(x)]=find(y); if(tree[rt<<1].rb[i]){ tree[rt].s1--; }else{ tree[rt].s0--; } } } for(int i=1;i<=n;i++) tree[rt].le[i]=find(tree[rt<<1].le[i]), tree[rt].ri[i]=find(tree[rt<<1|1].ri[i]); for(int i=1;i<=n;i++) tmp[i<<1]=tree[rt].le[i],tmp[(i<<1)-1]=tree[rt].ri[i]; sort(tmp+1,tmp+1+2*n); int mxdata=unique(tmp+1,tmp+1+2*n)-tmp-1; for(int i=1;i<=n;i++) tree[rt].le[i]=lower_bound(tmp+1,tmp+1+mxdata, tree[rt].le[i])-tmp,tree[rt].ri[i]=lower_bound(tmp+1,tmp+1+mxdata,tree[rt].ri[i])-tmp; for(int i=1;i<=n;i++) tree[rt<<1|1].le[i]-=2*n,tree[rt<<1|1].ri[i]-=2*n; } void build(int l,int r,int rt){ tree[rt].l=l;tree[rt].r=r; if(l==r){ int tot=0; for(int i=1;i<=n;i++) { if(a[i][l]!=a[i-1][l]) { tot++; if(a[i][l]) tree[rt].s1++; else tree[rt].s0++; } tree[rt].le[i]=tree[rt].ri[i]=tot; tree[rt].lb[i]=tree[rt].rb[i]=a[i][l]; } return; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); update(rt); } void modify(int rt,int pos) { if(tree[rt].l==tree[rt].r) { int tot=0;tree[rt].s1=0;tree[rt].s0=0; for(int i=1;i<=n;i++) { if(a[i][pos]!=a[i-1][pos]) { tot++; if(a[i][pos]) tree[rt].s1++; else tree[rt].s0++; } tree[rt].le[i]=tree[rt].ri[i]=tot; tree[rt].lb[i]=tree[rt].rb[i]=a[i][pos]; } return; } int mid=(tree[rt].l+tree[rt].r)>>1; if(pos<=mid) modify(rt<<1,pos); else modify(rt<<1|1,pos); update(rt); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ a[0][i]=-1; for(int j=1;j<=n;j++){ scanf("%d",&a[i][j]); } } build(1,n,1); scanf("%d",&m); while(m--){ int x,y; scanf("%d%d",&x,&y); a[x][y]^=1; modify(1,y); printf("%d %d\n",tree[1].s1,tree[1].s0); } return 0; }