插入算法:微改,第二个判断解释,如果某个非叶子节点是cover,但是此时更新他的叶子节点,然后递归回来更新父节点的时候即会得到错误的结果。本质上就是说之前因为省时间我们不需要更新到每个叶子节点,但是如果某个父节点是cover的,那涉及到它的子节点更新时候他的所有子节点都要更新。
统计算法:差不多不改,见程序。
代码/Code:
type
arr=record
l,r,color:longint;
cover:boolean;
end;
var
tree:array [0..400001] of arr;
n,t,m,ans,tk:longint;
procedure cre(p,b,e:longint);
var
m:longint;
begin
with tree[p] do
begin
l:=b; r:=e; color:=color or 1;
if l=r then exit;
m:=(b+e) div 2;
cre(p*2,b,m);
cre(p*2+1,m+1,e);
end;
end;
procedure ins(p,b,e,c:longint);
var
m:longint;
begin
with tree[p] do
begin
if (l=b) and (r=e) then
begin
color:=1 shl (c-1);
cover:=true;
exit;
end;
if cover then
begin
cover:=false;
tree[p*2].cover:=true;
tree[p*2].color:=color;
tree[p*2+1].cover:=true;
tree[p*2+1].color:=color;
end;
m:=(l+r) div 2;
if e<=m then ins(p*2,b,e,c) else
if b>m then ins(p*2+1,b,e,c) else
begin
ins(p*2,b,m,c);
ins(p*2+1,m+1,e,c);
end;
color:=tree[p*2].color or tree[p*2+1].color;
end;
end;
procedure count(p,b,e:longint);
var
m:longint;
begin
with tree[p] do
begin
if (cover) or (b=l) and (r=e) then
begin
tk:=tk or color;
exit;
end;
m:=(l+r) div 2;
if e<=m then count(p*2,b,e) else
if b>m then count(p*2+1,b,e) else
begin
count(p*2,b,m);
count(p*2+1,m+1,e);
end;
end;
end;
procedure main;
var
i,j,x,y,c,k:longint;
ch:char;
begin
readln(n,t,m);
cre(1,1,n);
for i:=1 to m do
begin
read(ch,x,y);
if x>y then
begin
k:=x; x:=y; y:=k;
end;
if ch='C' then
begin
readln(c);
ins(1,x,y,c);
end else
begin
readln;
ans:=0; tk:=0;
count(1,x,y);
for j:=1 to t do
if tk and (1 shl (j-1))>0 then
inc(ans);
writeln(ans);
end;
end;
end;
begin
main;
end.