zju1610 count the colors 线段树

来源:互联网 发布:cdr软件手机版 编辑:程序博客网 时间:2024/05/29 18:04

题目大意

  给n个线段,覆盖在一条直线上,每个线段都覆盖先前的线段(如果相重叠的话),每条线短都有自己的颜色,求最后有多少种颜色和每种颜色要多少段。

 

分析

  就是例二和例三的结合。

  首先定义cover如下:cover=-1表示该区间由多种颜色组成。cover>=0表示该区间只有一种单一的颜色cover。

  然后,统计算法就要做一下大的改动:

  递归定义改一改:function find(t:pnode;l,r:longint;var lo,ro:longint):longint;

  Lo,ro表示当前子树的最左边的颜色和最右边的颜色。

  使用一个数组Flag,初始化为0。统计线段树,对于找到的颜色c对Flag[c]加1。

  如果当前子树的左子树的最右边的颜色(c)等于右子树的最左边的颜色(c),且不等于颜色0,那代表有两条相连的段是同一种颜色(c)组成的(是一段),那就把flag[c]减一(因为计算左右子树时多计算了一次)。


代码

type  pnode=^tnode;  tnode=record    lc,rc:pnode;    c:longint;end;var  t:pnode;  i,j,k:longint;  x,y:longint;  n,m,nm:longint;  f:array[-2..100000] of longint;procedure neww(var t:pnode);begin  if t=nil then    begin      new(t);      t^.c:=-2;      t^.lc:=nil;      t^.rc:=nil;    end;end;procedure insert(var t:pnode; l,r,x,y,ce:longint);var  i,j,k:longint;  mid:longint;begin  with t^ do    begin      if c<>ce then        begin          mid:=(l+r) div 2;          if (l=x) and (r=y)            then              begin                c:=ce;                exit;              end;          if c<>-1            then              begin                neww(lc);                neww(rc);                lc^.c:=t^.c;                rc^.c:=t^.c;                t^.c:=-1;              end;          if (l<=x) and (mid>=y)            then              begin                neww(lc);                insert(lc,l,mid,x,y,ce);                exit;              end;          if (mid<=x) and (r>=y)            then              begin                neww(rc);                insert(rc,mid,r,x,y,ce);                exit;              end;          neww(lc);          neww(rc);          insert(lc,l,mid,x,mid,ce);          insert(rc,mid,r,mid,y,ce);        end;    end;end;procedure find(t:pnode;l,r:longint;var lo,ro:longint);var  mid,ans:longint;  tl,tr:longint;begin  if t=nil then exit;  with t^ do    begin      mid:=(l+r) div 2;      if c<>-1        then          begin            lo:=c;            ro:=c;            f[c]:=f[c]+1;            exit;          end;      find(lc,l,mid,lo,tl);      find(rc,mid,r,tr,ro);      if (tl=tr) and (tl<>-2) then        begin          ans:=ans-1;          f[tl]:=f[tl]-1;        end;    end;end;begin  while not eof do begin  readln(n);  m:=8000;  fillchar(t,sizeof(t),0);  fillchar(f,sizeof(f),0);  neww(t);  nm:=0;  for i:=1 to n do    begin      readln(x,y,j);      insert(t,0,m,x,y,j);      if j>nm then nm:=j;    end;  i:=0; j:=0;  find(t,0,m,i,j);  for i:=0 to nm do    if f[i]<>0 then writeln(i,' ',f[i]);  writeln;  end;end.


1 0
原创粉丝点击