zoukankan      html  css  js  c++  java
  • bzoj1453

    这是一道好题,按行建线段树,每个点维护上下边界的连通性,详细见代码注释

    网上写法不一,自认为比较简单,就放出来相出来献丑吧

      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.
    View Code
  • 相关阅读:
    linux环境下的时间编程
    golang1.13中重要的新特新
    vs2019+cmake实现Linux远程开发
    现代c++与模板元编程
    一个commit引发的思考
    golang中判断两个slice是否相等
    c++性能测试工具:计算时间复杂度
    c++性能测试工具:google benchmark入门(二)
    使用vs2019进行Linux远程开发
    智能指针和二叉树(3):图解查找和删除
  • 原文地址:https://www.cnblogs.com/phile/p/4490674.html
Copyright © 2011-2022 走看看