原题:ZJOI2008 count
方法:块状树
program count_trees;{$M 9999999}
const maxn=30000+20;
type
link=^node; node=record x:longint; next:link; end;
var
own,w,dep,sum,size,fa,mun:array[0..maxn]of longint;
ge,g:array[1..maxn]of link; limit:longint;
procedure update(var x:longint; const y:longint);
begin
if y>x then x:=y;
end;
procedure push(var x:link; const t:longint);var p:link;
begin
new(p);p^.x:=t;p^.next:=x;x:=p;
end;
procedure build(const x,f,d:longint);
var p:link;tmp:longint;
begin
fa[x]:=f; dep[x]:=d; tmp:=own[x];
p:=ge[x];while p<>nil do begin
if p^.x<>f then begin
if size[tmp]<limit then begin
inc(size[tmp]);own[p^.x]:=tmp;
push(g[x],p^.x);
end;build(p^.x,x,d+1);end;
p:=p^.next;
end;
end;
procedure dfs(x,s,m:longint);var p:link;
begin
inc(s,w[x]);sum[x]:=s;
update(m,w[x]);mun[x]:=m;
p:=g[x];while p<>nil do begin Dfs(p^.x,s,m);p:=p^.next;end;
end;
procedure change(x,y:longint);
begin
w[x]:=y;if x=own[x] then Dfs(x,0,-maxlongint)
else dfs(x,sum[fa[x]],mun[fa[x]]);
end;
procedure get_answer(a,b:longint; var s,m:longint);
procedure swap(var i,j:longint);var t:longint;
begin t:=i; i:=j; j:=t; end;
begin
s:=0;m:=-maxlongint;
while a<>b do begin
if dep[a]<dep[b] then swap(a,b);
if own[a]=own[b] then begin
inc(s,w[a]);update(m,w[a]);
a:=fa[a];
end else begin
if dep[own[a]]<dep[own[b]] then swap(a,b);
inc(s,sum[a]);update(m,mun[a]);
a:=fa[own[a]];
end;
end;
inc(s,w[a]);update(m,w[a]);
end;
function readspace:char;var c:char;
begin
read(c);read(c);readspace:=c;
while c<>' ' do read(c);
end;
var n,i,x,y,que,s,m:longint; ch:char;
begin
readln(n);limit:=trunc(sqrt(n));
for i:=1 to n-1 do begin readln(x,y);push(ge[x],y);push(ge[y],x);end;
for i:=1 to n do begin read(w[i]);own[i]:=i;end;build(1,0,1);
for i:=1 to n do if own[i]=i then Dfs(i,0,-maxlongint);
readln(que);for que:=1 to que do begin
ch:=readspace;readln(x,y);
if ch='H' then change(x,y) else begin
get_answer(x,y,s,m);
if ch='S' then writeln(s) else writeln(m);
end;
end;
end.