2646 线段树练习题三

来源:互联网 发布:播放软件大全排行 编辑:程序博客网 时间:2024/05/18 00:59

  • 题目
  • 题解
  • 代码

题目

给定一条长度为m的线段,有n个操作,每个操作有3个数字x,y,z表示把区间[x,y]染成颜色z,询问染完色之后,这条长度为m的线段一共有几种颜色。规定:线段的颜色可以相同。连续的相同颜色被视作一段。问x轴被分成多少段。
N <= 10000
M <= 1000000

题解

线段树,和练习题二的插入算法一样。

统计时,若一个区间由单一颜色组成,则把该区间的边界颜色(即最左和最右)作为变量形参带回上一区间,并将返回值设为1
若由多种颜色组成,则递归它的左右儿子,把左右儿子的返回值相加作为自己的返回值,并比较两个字区间的相交部分(即左儿子的最右和右儿子的最左)颜色,若相同且不为-1,则返回值减1

最后输出统计的返回值

时间复杂度O(n log m)

代码

type  bec=record        b,e:longint;        c:longint;      end;var  n,m,i,x,y,z,j,k,ans:longint;  t:array[1..1000000]of bec;procedure setup(p:longint);var  m:longint;begin  if t[p].e-t[p].b>1 then    begin      m:=(t[p].e+t[p].b) div 2;      t[p*2].b:=t[p].b;      t[p*2].e:=m;      t[p*2+1].b:=m;      t[p*2+1].e:=t[p].e;      setup(p*2);      setup(p*2+1);    end;end;procedure insert(p,x,y,z:longint);var  m:longint;begin  if t[p].c<>z then    begin      if (x=t[p].b)and(y=t[p].e) then t[p].c:=z else        begin          m:=(t[p].b+t[p].e)div 2;          if t[p].c>=0 then            begin              t[p*2].c:=t[p].c;              t[p*2+1].c:=t[p].c;              t[p].c:=-1;            end;          if y<=m then insert(p*2,x,y,z) else          if x>=m then insert(p*2+1,x,y,z) else            begin              insert(p*2,x,m,z);              insert(p*2+1,m,y,z);            end;        end;    end;end;function count(p:longint;var l,r:longint):longint;var  k,d,e:longint;begin  if t[p].c>=0 then    begin      l:=t[p].c;r:=t[p].c;      count:=1;      exit;    end;  if t[p].e-t[p].b>1 then    begin      k:=count(p*2,l,d)+count(p*2+1,e,r);      if (d=e)and(l>=0) then dec(k);      count:=k;    end;end;begin  readln(n,m);  t[1].b:=1;t[1].e:=m;  setup(1);  for i:=1 to n do    begin      readln(x,y,z);      insert(1,x,y,z);    end;  writeln(count(1,x,y));end.
1 0