【BZOJ1453】[Wc]Dface双面棋盘
Description
Input
Output
Sample Input
Sample Output
HINT
题解:话说看到题的第一反应其实是LCT。。。还是学学正解的写法吧(虽然复杂度不如LCT)。
我们用线段树维护所有的行,每个叶子节点都代表一个列,每个线段树的节点都维护如下信息:左面那列的连通情况(用并查集维护),右面那列的连通情况,左面那列的颜色,右面那列的颜色。合并的时候枚举中间的那列,如果相邻颜色相同则进行并查集合并。特别地,如果在合并后,一些点在并查集中的根是中间的点,那么我们要将这些点的根变为两边的点,细节什么的仔细想一想就好。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define lson x<<1 #define rson x<<1|1 using namespace std; int n,m; int v[210][210]; struct sag { int f[810],c[410],s[2]; int find(int x) { return (f[x]==x)?x:(f[x]=find(f[x])); } friend sag operator + (const sag &a,const sag &b) { sag c; int i; c.s[0]=a.s[0]+b.s[0],c.s[1]=a.s[1]+b.s[1]; for(i=1;i<=n;i++) { c.c[i]=a.c[i],c.c[i+n]=b.c[i+n],c.f[i]=a.f[i],c.f[i+n]=b.f[i+n],c.f[i+2*n]=a.f[i+n],c.f[i+3*n]=b.f[i]; if(c.f[i]>n) c.f[i]+=n; if(c.f[i+n]<=n) c.f[i+n]+=3*n; if(c.f[i+2*n]>n) c.f[i+2*n]+=n; if(c.f[i+3*n]<=n) c.f[i+3*n]+=3*n; } for(i=1;i<=n;i++) if(a.c[i+n]==b.c[i]&&c.find(i+2*n)!=c.find(i+3*n)) c.s[a.c[i+n]]--,c.f[c.f[i+2*n]]=c.f[i+3*n]; //for(i=1;i<=(n<<2);i++) c.find(i),c.find(i+2*n); for(i=1;i<=(n<<1);i++) if(c.find(i)>2*n) c.f[c.f[i]]=i,c.f[i]=i; for(i=1;i<=(n<<1);i++) c.find(i); return c; } }s[810]; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar(); return ret*f; } void build(int l,int r,int x) { if(l==r) { for(int i=1;i<=n;i++) { s[x].c[i]=s[x].c[i+n]=v[l][i]; if(i!=1&&v[l][i]==v[l][i-1]) s[x].f[i]=s[x].f[i+n]=s[x].f[i-1]; else s[x].f[i]=s[x].f[i+n]=i,s[x].s[v[l][i]]++; } return ; } int mid=(l+r)>>1; build(l,mid,lson),build(mid+1,r,rson); s[x]=s[lson]+s[rson]; } void updata(int l,int r,int x,int a,int b) { if(l==r) { s[x].c[b]^=1,s[x].c[b+n]^=1,s[x].s[0]=s[x].s[1]=0; for(int i=1;i<=n;i++) { if(i!=1&&s[x].c[i]==s[x].c[i-1]) s[x].f[i]=s[x].f[i+n]=s[x].f[i-1]; else s[x].f[i]=s[x].f[i+n]=i,s[x].s[s[x].c[i]]++; } return ; } int mid=(l+r)>>1; if(a<=mid) updata(l,mid,lson,a,b); else updata(mid+1,r,rson,a,b); s[x]=s[lson]+s[rson]; } int main() { n=rd(); int i,j,a,b; for(i=1;i<=n;i++) for(j=1;j<=n;j++) v[i][j]=rd(); build(1,n,1); m=rd(); for(i=1;i<=m;i++) { a=rd(),b=rd(); updata(1,n,1,a,b); printf("%d %d ",s[1].s[1],s[1].s[0]); } return 0; }//5 0 1 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 2 3 2 2 3