线段树 例三
题目大意
把例2稍加改动,规定:线段的颜色可以相同。连续的相同颜色被视作一段。问x轴被分成多少段。
分析
仍然定义cover如下:cover=-1表示该区间由多种颜色组成。cover>=0表示该区间只有一种单一的颜色cover。
但是,统计算法就要做一下大的改动:
递归定义改一改:function find(t:pnode;l,r:longint;var lo,ro:longint):longint;
Lo,ro表示当前子树的最左边的颜色和最右边的颜色。
如果当前子树的左子树的最右边的颜色等于右子树的最左边的颜色,且不等于颜色0,那代表有两条相连的段是同一种颜色组成的(是一段),那总段数要减一(因为计算左右子树时多计算了一次)。
代码
type pnode=^tnode; tnode=record lc,rc:pnode; c:longint; end; var t:pnode; i,j,k:longint; x,y:longint; n,m:longint; f:array[0..100000] of longint; procedure neww(var t:pnode); begin if t=nil then begin new(t); t^.c:=0; 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; function find(t:pnode;l,r:longint;var lo,ro:longint):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; find:=1; exit; end; ans:=find(lc,l,mid,lo,tl)+find(rc,mid,r,tr,ro); if (tl=tr) and (tl<>0) then ans:=ans-1; find:=ans; end; end; begin readln(n,m); fillchar(t,sizeof(t),0); neww(t); for i:=1 to n do begin readln(x,y,j); insert(t,1,m,x,y,j); end; i:=0; j:=0; write(find(t,1,m,i,j)); end.