这是一道好题,按行建线段树,每个点维护上下边界的连通性,详细见代码注释
网上写法不一,自认为比较简单,就放出来相出来献丑吧
1 var u,d:array[0..810,0..205] of longint; //u[]上边界,d[]下边界 2 s,fa,q:array[0..810] of longint; 3 c:array[0..810,0..1] of longint; //维护对应颜色块数 4 a:array[0..205,0..205] of longint; 5 j,i,n,m,x,y:longint; 6 7 function getf(x:longint):longint; 8 begin 9 if fa[x]<>x then fa[x]:=getf(fa[x]); 10 exit(fa[x]); 11 end; 12 13 procedure union(i,m:longint); 14 var j,k1,k2,t:longint; 15 begin 16 c[i,0]:=c[i*2,0]+c[i*2+1,0]; 17 c[i,1]:=c[i*2,1]+c[i*2+1,1]; 18 for j:=1 to n do 19 begin 20 fa[j]:=u[i*2,j]; 21 fa[j+n]:=d[i*2,j]; 22 fa[j+2*n]:=u[i*2+1,j]+2*n; //防止编号重复 23 fa[j+3*n]:=d[i*2+1,j]+2*n; 24 end; 25 for j:=1 to n do 26 if a[m+1,j]=a[m,j] then //子区间相邻连通块合并 27 begin 28 k1:=getf(fa[j+n]); 29 k2:=getf(fa[j+2*n]); 30 if k1<>k2 then 31 begin 32 fa[k2]:=k1; 33 dec(c[i,a[m,j]]); 34 end; 35 end; 36 t:=0; 37 for j:=1 to n do 38 begin 39 k1:=getf(fa[j]); //对整个区间上边界连通性重新标号 40 if s[k1]=0 then 41 begin 42 inc(t); 43 q[t]:=k1; 44 s[k1]:=j; 45 end; 46 u[i,j]:=s[k1]; 47 k2:=getf(fa[j+3*n]); //对整个区间下边界连通性重新标号 48 if s[k2]=0 then 49 begin 50 inc(t); 51 q[t]:=k2; 52 s[k2]:=j+n; //防止编号重复,上边界编号1~n,下边界编号n+1~2n 53 end; 54 d[i,j]:=s[k2]; 55 end; 56 for j:=1 to t do 57 s[q[j]]:=0; 58 end; 59 60 procedure leaf(i,row:longint); 61 var j,t:longint; 62 begin 63 t:=0; 64 c[i,0]:=0; c[i,1]:=0; 65 for j:=1 to n do 66 if (j<>1) and (a[row,j]=a[row,j-1]) then 67 begin 68 u[i,j]:=u[i,j-1]; 69 d[i,j]:=d[i,j-1]; 70 end 71 else begin 72 inc(c[i,a[row,j]]); 73 u[i,j]:=j; d[i,j]:=j; //连通块以起始位置为编号,这样比较方便 74 end; 75 end; 76 77 procedure build(i,l,r:longint); 78 var m:longint; 79 begin 80 if l=r then leaf(i,l) 81 else begin 82 m:=(l+r) shr 1; 83 build(i*2,l,m); 84 build(i*2+1,m+1,r); 85 union(i,m); 86 end; 87 end; 88 89 procedure work(i,l,r:longint); 90 var m:longint; 91 begin 92 if l=r then leaf(i,l) 93 else begin 94 m:=(l+r) shr 1; 95 if x<=m then work(i*2,l,m) 96 else work(i*2+1,m+1,r); 97 union(i,m); 98 end; 99 end; 100 101 begin 102 readln(n); 103 for i:=1 to n do 104 for j:=1 to n do 105 read(a[i,j]); 106 build(1,1,n); 107 readln(m); 108 for i:=1 to m do 109 begin 110 readln(x,y); 111 a[x,y]:=1-a[x,y]; 112 work(1,1,n); 113 writeln(c[1,1],' ',c[1,0]); 114 end; 115 end.