树链剖分是分块的思想
将树上所有边分成轻重边,把重边连成重链,把轻边单独维护,重边连成的链放在数据结构中,根据两点间重链和轻边数量的限制,使得时间复杂度能够令人满意
时间复杂度:每次走 logN 级别的轻边和重链,线段树上修改重边是 logN 级别,总复杂度为 O(Qlog2N)
空间复杂度:线段树的复杂度 O(NlogN)
参考[BZOJ1036] [ZJOI2008]树的统计Count
const
maxn=30010;
type
data=record sum,max:longint; end;
var
w:array[0..3*maxn,1..2]of longint;
seg:array[0..8*maxn,1..4]of longint; {seg[i,3]:sum; seg[i,4]:max}
pos,val,size,top,son,fa,dep:array[0..maxn]of longint;
i,j,k:longint;
n,m,len,a,b:longint;
cha,ch:char;
function mmax(a,b:longint):longint;
begin if a>b then exit(a) else exit(b); 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]:=0; seg[a,4]:=0;
if l=r then exit;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;
procedure update(a,b,c:longint);
var mid:longint;
begin
if seg[a,1]=seg[a,2] then begin seg[a,3]:=c; seg[a,4]:=c; exit; end;
mid:=(seg[a,1]+seg[a,2])>>1;
if b<=mid
then update(a<<1,b,c) else update(a<<1+1,b,c);
seg[a,3]:=seg[a<<1,3]+seg[a<<1+1,3]; seg[a,4]:=mmax(seg[a<<1,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,1]=l)and(seg[a,2]=r) then begin ans.sum:=seg[a,3]; ans.max:=seg[a,4]; 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.sum:=t1.sum+t2.sum; ans.max:=mmax(t1.max,t2.max); exit(ans); end;
end;
procedure dfs1(a:longint); {size[],son[],fa[],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); {top[],pos[]}
var tt:longint;
begin
tt:=w[a,2]; top[a]:=pre; inc(len); pos[a]:=len; update(1,len,val[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;
function queryans(a,b:longint):data;
var tt:longint; t1,ans:data;
begin
ans.sum:=0; ans.max:=-maxlongint;
while top[a]<>top[b] do
begin
if dep[top[a]]<dep[top[b]] then begin tt:=a; a:=b; b:=tt; end;
t1:=query(1,pos[top[a]],pos[a]);
inc(ans.sum,t1.sum); ans.max:=mmax(ans.max,t1.max);
a:=fa[top[a]];
end;
if dep[a]>dep[b] then begin tt:=a; a:=b; b:=tt; end;
t1:=query(1,pos[a],pos[b]);
inc(ans.sum,t1.sum); ans.max:=mmax(ans.max,t1.max);
exit(ans);
end;
begin
readln(n); len:=n+1;
for i:=1 to n-1 do
begin
readln(a,b);
init(a,b); init(b,a);
end;
for i:=1 to n do
read(val[i]);
dep[1]:=1; fa[1]:=0; size[0]:=0;
dfs1(1);
build(1,1,n); len:=0;
dfs2(1,1);
readln(m);
for i:=1 to m do
begin
read(cha,ch);
case ch of
'H':begin readln(cha,cha,cha,cha,a,b); val[a]:=b; update(1,pos[a],b)3B end;
'S':begin readln(cha,cha,a,b); writeln(queryans(a,b).sum); end;
'M':begin readln(cha,cha,a,b); writeln(queryans(a,b).max); end;
end;
end;
end.