传送门
http://www.lydsy.com/JudgeOnline/problem.php?id=2243
题目大意
支持
1.树链染色
2.查询树链颜色段数
题解
树剖后线段树维护区间左端点颜色右端点颜色和颜色段数,合并自己yy以下就好了,两条链向上合并时注意细节
{$M 100000000,0,100000000}
const
maxn=100010;
type
data=record l,r,sum:longint; end;
var
w:array[0..3*maxn,1..2]of longint;
seg:array[0..8*maxn,1..6]of longint;
x,pos,top,fa,son,size,dep:array[0..maxn]of longint;
i,j,k:longint;
n,m,len,a,b,c,t1,t2:longint;
cha,ch:char;
procedure swap(var a,b:longint);
var tt:longint;
begin tt:=a; a:=b; b:=tt; end;
procedure init(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0 then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
seg[a,1]:=l; seg[a,2]:=r; seg[a,3]:=-1; seg[a,4]:=-1; seg[a,5]:=0; seg[a,6]:=-1;
if l=r then exit;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;
procedure pushdown(a:longint);
begin
if seg[a,1]=seg[a,2] then begin seg[a,6]:=-1; exit; end;
seg[a<<1,3]:=seg[a,6]; seg[a<<1,4]:=seg[a,6]; seg[a<<1,5]:=1; seg[a<<1,6]:=seg[a,6];
seg[a<<1+1,3]:=seg[a,6]; seg[a<<1+1,4]:=seg[a,6]; seg[a<<1+1,5]:=1; seg[a<<1+1,6]:=seg[a,6];
seg[a,6]:=-1;
end;
procedure update(a,l,r,b:longint);
var mid:longint;
begin
if seg[a,6]<>-1 then pushdown(a);
if (seg[a,1]=l)and(seg[a,2]=r) then begin seg[a,3]:=b; seg[a,4]:=b; seg[a,5]:=1; seg[a,6]:=b; exit; end;
mid:=(seg[a,1]+seg[a,2])>>1;
if r<=mid then update(a<<1,l,r,b) else
if l>mid then update(a<<1+1,l,r,b)
else begin update(a<<1,l,mid,b); update(a<<1+1,mid+1,r,b); end;
seg[a,5]:=seg[a<<1,5]+seg[a<<1+1,5]; if seg[a<<1,4]=seg[a<<1+1,3] then dec(seg[a,5]);
seg[a,3]:=seg[a<<1,3]; seg[a,4]:=seg[a<<1+1,4];
end;
function query(a,l,r:longint):data;
var mid:longint; ans,t1,t2:data;
begin
if seg[a,6]<>-1 then pushdown(a);
if (seg[a,1]=l)and(seg[a,2]=r) then begin ans.l:=seg[a,3]; ans.r:=seg[a,4]; ans.sum:=seg[a,5]; exit(ans); end;
mid:=(seg[a,1]+seg[a,2])>>1;
if r<=mid then exit(query(a<<1,l,r)) else
if l>mid then exit(query(a<<1+1,l,r))
else
begin
t1:=query(a<<1,l,mid);
t2:=query(a<<1+1,mid+1,r);
ans.l:=t1.l; ans.r:=t2.r; ans.sum:=t1.sum+t2.sum;
if t1.r=t2.l then dec(ans.sum);
exit(ans);
end;
end;
procedure dfs1(a:longint); {fa,son,size,dep}
var tt,v:longint;
begin
tt:=w[a,2]; size[a]:=1; v:=0;
while tt<>0 do
begin
if w[tt,1]<>fa[a]
then
begin
fa[w[tt,1]]:=a; dep[w[tt,1]]:=dep[a]+1;
dfs1(w[tt,1]);
inc(size[a],size[w[tt,1]]); if size[w[tt,1]]>size[v] then v:=w[tt,1];
end;
tt:=w[tt,2];
end;
son[a]:=v;
end;
procedure dfs2(a,pre:longint);
var tt:longint;
begin
tt:=w[a,2]; top[a]:=pre; inc(len); pos[a]:=len; update(1,pos[a],pos[a],x[a]);
if son[a]<>0 then dfs2(son[a],pre);
while tt<>0 do
begin
if (w[tt,1]<>fa[a])and(w[tt,1]<>son[a]) then dfs2(w[tt,1],w[tt,1]);
tt:=w[tt,2];
end;
end;
procedure change(a,b,c:longint);
begin
while top[a]<>top[b] do
begin
if dep[top[a]]<dep[top[b]] then swap(a,b);
update(1,pos[top[a]],pos[a],c);
a:=fa[top[a]];
end;
if dep[a]>dep[b] then swap(a,b);
update(1,pos[a],pos[b],c);
end;
function queryans(a,b:longint):longint;
var tt,t1,t2:data;
begin
t1.l:=-1; t1.r:=-1; t1.sum:=0; t2.l:=-1; t2.r:=-1; t2.sum:=0;
while top[a]<>top[b] do
begin
if dep[top[a]]<dep[top[b]] then begin swap(a,b); tt:=t1; t1:=t2; t2:=tt; end;
tt:=query(1,pos[top[a]],pos[a]);
if tt.r=t1.l then t1.sum:=tt.sum+t1.sum-1 else t1.sum:=tt.sum+t1.sum;
t1.l:=tt.l;
a:=fa[top[a]];
end;
if dep[a]>dep[b] then begin swap(a,b); tt:=t1; t1:=t2; t2:=tt; end;
tt:=query(1,pos[a],pos[b]);
if tt.l=t1.l then t1.sum:=t1.sum+tt.sum-1 else t1.sum:=t1.sum+tt.sum;
t1.l:=tt.r;
if t1.l=t2.l then t1.sum:=t1.sum+t2.sum-1 else t1.sum:=t1.sum+t2.sum;
exit(t1.sum);
end;
begin
readln(n,m); len:=n+1;
for i:=1 to n do
read(x[i]);
for i:=1 to n-1 do
begin
readln(a,b);
init(a,b); init(b,a);
end;
dep[1]:=1; fa[1]:=0; size[0]:=0;
dfs1(1);
build(1,1,n); len:=0;
dfs2(1,1);
for i:=1 to m do
begin
read(cha);
if cha='C'
then begin readln(a,b,c); change(a,b,c); end
else begin readln(a,b); writeln(queryans(a,b)); end;
end;
end.