题目
给定一条长度为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.