题意:
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
思路:树上的路径染色问题可以用树剖解决。
对于线段树的某个节点我们记录以下信息:最左端颜色,最右端颜色,整段中段数,以及lazytag。
其中lazytag>=0时表示该区间要改成什么颜色,-1表示当前节点没有标记。
转换到树上做即可
BZOJ过了样例就一遍过(萎靡)
type un=record
l,r,s,tag:longint;
end;
var t:array[..]of un;
f:array[..,..]of longint;
head,vet,next,flag,dep,fa,top,
tid,id,size,son,a:array[..]of longint;
n,m,i,j,k,x,y,z,q,tot,time:longint;
ch:string;
emp:un; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure add(a,b:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
head[a]:=tot;
end; procedure dfs1(u:longint);
var e,v,maxsize,i:longint;
begin
flag[u]:=; size[u]:=; maxsize:=; son[u]:=;
for i:= to do
begin
if dep[u]<(<<i) then break;
f[u,i]:=f[f[u,i-],i-];
end; e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
dep[v]:=dep[u]+;
f[v,]:=u;
fa[v]:=u;
dfs1(v);
size[u]:=size[u]+size[v];
if size[v]>maxsize then
begin
maxsize:=size[v];
son[u]:=v;
end;
end;
e:=next[e];
end;
end; procedure dfs2(u,ance:longint);
var e,v:longint;
begin
flag[u]:=; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance;
if son[u]> then dfs2(son[u],ance);
e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then dfs2(v,v);
e:=next[e];
end;
end; function lca(x,y:longint):longint;
var i,d:longint;
begin
if dep[x]<dep[y] then swap(x,y);
d:=dep[x]-dep[y];
for i:= to do
if d and (<<i)> then x:=f[x,i];
for i:= downto do
if f[x,i]<>f[y,i] then
begin
x:=f[x,i]; y:=f[y,i];
end;
if x=y then exit(x);
exit(f[x,]);
end; procedure pushup(p:longint);
begin
t[p].l:=t[p<<].l; t[p].r:=t[p<<+].r;
if t[p<<].r<>t[p<<+].l then t[p].s:=t[p<<].s+t[p<<+].s
else t[p].s:=t[p<<].s+t[p<<+].s-;
end; procedure pushdown(p,l,r:longint);
var tmp:longint;
begin
tmp:=t[p].tag; t[p].tag:=-;
if (tmp=-)or(l=r) then exit;
t[p<<].s:=; t[p<<+].s:=;
t[p<<].tag:=tmp; t[p<<+].tag:=tmp;
t[p<<].l:=tmp; t[p<<].r:=tmp;
t[p<<+].l:=tmp; t[p<<+].r:=tmp;
end; procedure build(l,r,p:longint);
var mid:longint;
begin
if l=r then
begin
t[p].s:=;
t[p].tag:=-;
exit;
end;
t[p].tag:=-;
mid:=(l+r)>>;
build(l,mid,p<<);
build(mid+,r,p<<+);
end; procedure update(l,r,x,y,v,p:longint);
var mid:longint;
begin
pushdown(p,l,r);
if (l>=x)and(r<=y) then
begin
t[p].l:=v; t[p].r:=v;
t[p].s:=; t[p].tag:=v;
exit;
end;
mid:=(l+r)>>;
if x<=mid then update(l,mid,x,y,v,p<<);
if y>mid then update(mid+,r,x,y,v,p<<+);
pushup(p);
end; function query(l,r,x,y,p:longint):longint;
var mid,t1,t2:longint;
begin
pushdown(p,l,r);
if (l>=x)and(r<=y) then exit(t[p].s);
mid:=(l+r)>>;
t1:=; t2:=;
if x<=mid then t1:=query(l,mid,x,y,p<<);
if y>mid then t2:=query(mid+,r,x,y,p<<+);
if t1= then exit(t2);
if t2= then exit(t1);
query:=t1+t2;
if t[p<<].r=t[p<<+].l then dec(query);
end; function get(l,r,x,p:longint):longint;
var mid:longint;
begin
pushdown(p,l,r);
if (l=x)and(r=x) then exit(t[p].l);
mid:=(l+r)>>;
if x<=mid then exit(get(l,mid,x,p<<))
else exit(get(mid+,r,x,p<<+));
end; function ask(x,y:longint):longint;
var q:longint;
begin
q:=lca(x,y);
ask:=;
while top[x]<>top[q] do
begin
ask:=ask+query(,n,tid[top[x]],tid[x],);
if get(,n,tid[top[x]],)=get(,n,tid[fa[top[x]]],) then dec(ask);
x:=fa[top[x]];
end;
ask:=ask+query(,n,tid[q],tid[x],);
while top[y]<>top[q] do
begin
ask:=ask+query(,n,tid[top[y]],tid[y],);
if get(,n,tid[top[y]],)=get(,n,tid[fa[top[y]]],) then dec(ask);
y:=fa[top[y]];
end;
ask:=ask+query(,n,tid[q],tid[y],);
dec(ask); end; procedure solve(x,y,z:longint);
var q:longint;
begin
q:=lca(x,y);
while top[x]<>top[q] do
begin
update(,n,tid[top[x]],tid[x],z,);
x:=fa[top[x]];
end;
update(,n,tid[q],tid[x],z,);
while top[y]<>top[q] do
begin
update(,n,tid[top[y]],tid[y],z,);
y:=fa[top[y]];
end;
update(,n,tid[q],tid[y],z,);
end; begin
assign(input,'bzoj2243.in'); reset(input);
assign(output,'bzoj2243.out'); rewrite(output);
readln(n,m);
for i:= to n do read(a[i]);
for i:= to n- do
begin
readln(x,y);
add(x,y);
add(y,x);
end;
dfs1();
fillchar(flag,sizeof(flag),);
dfs2(,);
build(,n,);
for i:= to n do update(,n,tid[i],tid[i],a[i],);
//for i:= to n do write(a[id[i]],' ');
for i:= to m do
begin
readln(ch);
x:=; y:=; z:=;
case ch[] of
'C':
begin
for k:= to length(ch) do
begin
if ch[k]=' ' then break;
x:=x*+ord(ch[k])-ord('');
end;
j:=k+;
for k:=j to length(ch) do
begin
if ch[k]=' ' then break;
y:=y*+ord(ch[k])-ord('');
end;
j:=k+;
for k:=j to length(ch) do z:=z*+ord(ch[k])-ord('');
solve(x,y,z);
end; 'Q':
begin
for k:= to length(ch) do
begin
if ch[k]=' ' then break;
x:=x*+ord(ch[k])-ord('');
end;
j:=k+;
for k:=j to length(ch) do y:=y*+ord(ch[k])-ord('');
writeln(ask(x,y));
end;
end;
end;
close(input);
close(output);
end.