首先发现是一棵树,想到树链剖分来维护路径。
但是如何把不同宗教的点分开计数?想到给每一个宗教开一颗线段树来维护,因为总共点数只有10^5个,可以采取动态开点来保证内存不超。
代码
type
xtree=^xtreenode;
xtreenode=record
max,sum,l,r:longint;
ls,rs:xtree;
end;
edge=^edgenode;
edgenode=record
t:longint;
next:edge;
end;
var
n,q,i,j,u,v,time,ans,ck,x,y:longint;
c1:char;
w,c,dfn,fdfn,deep,size,head,hs,fa:array[0..100100]of longint;
con:array[1..100100]of edge;
xtr:array[1..100100]of xtree;
procedure ins(x,y:longint);
var
p:edge;
begin
new(p);
p^.t:=y;
p^.next:=con[x];
con[x]:=p;
end;
function maxx(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
procedure outp(x:xtree);
begin
if x=nil then exit;
writeln(x^.l,' ',x^.r,' ',x^.max,' ',x^.sum);
outp(x^.ls);
outp(x^.rs);
end;
procedure dfs1(v:longint);
var
p:edge;
max,maxi:longint;
begin
size[v]:=1;
deep[v]:=deep[fa[v]]+1;
p:=con[v];
max:=0;
maxi:=0;
while p<>nil do
begin
if p^.t<>fa[v] then
begin
fa[p^.t]:=v;
dfs1(p^.t);
if size[p^.t]>max then begin max:=size[p^.t]; maxi:=p^.t end;
size[v]:=size[v]+size[p^.t];
end;
p:=p^.next;
end;
hs[v]:=maxi;
end;
procedure dfs2(v:longint);
var
p:edge;
begin
inc(time);
dfn[v]:=time;
fdfn[time]:=v;
if hs[fa[v]]=v then head[v]:=head[fa[v]]
else head[v]:=v;
p:=con[v];
if hs[v]>0 then dfs2(hs[v]);
while p<>nil do
begin
if (p^.t<>fa[v])and(p^.t<>hs[v]) then dfs2(p^.t);
p:=p^.next;
end;
end;
procedure build(var x:xtree;sum,max,l,r:longint);
begin
new(x);
x^.l:=l;
x^.r:=r;
x^.max:=max;
x^.sum:=sum;
x^.ls:=nil;
x^.rs:=nil;
end;
procedure updata(var x:xtree);
begin
x^.sum:=0;
x^.max:=0;
if x^.ls<>nil then begin x^.sum:=x^.ls^.sum; x^.max:=x^.ls^.max; end;
if x^.rs<>nil then begin x^.sum:=x^.sum+x^.rs^.sum; x^.max:=maxx(x^.max,x^.rs^.max) ; end;
end;
procedure change(var x:xtree;v,nw,l,r:longint);
var
mid:longint;
begin
if x=nil then build(x,0,0,l,r);
if l=r then begin x^.max:=nw; x^.sum:=nw; exit; end;
mid:=(l+r) div 2;
if (v>=l)and(v<=mid) then change(x^.ls,v,nw,l,mid)
else change(x^.rs,v,nw,mid+1,r);
updata(x);
end;
procedure dele(var x:xtree;v,nw,l,r:longint);
var
mid:longint;
begin
if l=r then begin x:=nil; exit; end;
mid:=(l+r) div 2;
if (v>=l)and(v<=mid) then dele(x^.ls,v,nw,l,mid)
else dele(x^.rs,v,nw,mid+1,r);
updata(x);
if x^.sum=0 then begin x:=nil; exit; end;
end;
function qsum(x:xtree;l,r:longint):longint;
var
mid:longint;
begin
if x=nil then exit(0);
if (l=x^.l)and(r=x^.r) then exit(x^.sum);
mid:=(x^.l+x^.r)div 2;
if r<=mid then exit(qsum(x^.ls,l,r));
if l>mid then exit(qsum(x^.rs,l,r));
exit(qsum(x^.ls,l,mid)+qsum(x^.rs,mid+1,r));
end;
function qmax(x:xtree;l,r:longint):longint;
var
mid:longint;
begin
if x=nil then exit(0);
if (l=x^.l)and(r=x^.r) then exit(x^.max);
mid:=(x^.l+x^.r)div 2;
if r<=mid then exit(qmax(x^.ls,l,r));
if l>mid then exit(qmax(x^.rs,l,r));
exit(maxx(qmax(x^.ls,l,mid),qmax(x^.rs,mid+1,r)));
end;
begin
readln(n,q);
for i:=1 to n do
readln(w[i],c[i]);
for i:=1 to n-1 do
begin
readln(u,v);
ins(u,v);
ins(v,u);
end;
dfs1(1);
dfs2(1);
for i:=1 to n do
change(xtr[c[i]],dfn[i],w[i],1,n);
for i:=1 to q do
begin
{for j:=1 to 3 do
begin
outp(xtr[j]);
writeln;
end; }
ans:=0;
read(c1);read(c1); readln(x,y);
ck:=c[x];
case c1 of
'C':begin dele(xtr[c[x]],dfn[x],w[x],1,n); c[x]:=y; change(xtr[y],dfn[x],w[x],1,n) end;
'W':begin w[x]:=y; change(xtr[c[x]],dfn[x],y,1,n) end;
'S':
begin
while head[x]<>head[y] do
begin
if deep[head[x]]>deep[head[y]] then
begin
ans:=ans+qsum(xtr[ck],dfn[head[x]],dfn[x]);
x:=fa[head[x]];
end
else
begin
ans:=ans+qsum(xtr[ck],dfn[head[y]],dfn[y]);
y:=fa[head[y]];
end;
end;
if deep[x]<=deep[y] then ans:=ans+qsum(xtr[ck],dfn[x],dfn[y])
else ans:=ans+qsum(xtr[ck],dfn[y],dfn[x]);
writeln(ans);
end;
'M':
begin
while head[x]<>head[y] do
begin
if deep[head[x]]>deep[head[y]] then
begin
ans:=maxx(ans,qmax(xtr[ck],dfn[head[x]],dfn[x]));
x:=fa[head[x]];
end
else
begin
ans:=maxx(ans,qmax(xtr[ck],dfn[head[y]],dfn[y]));
y:=fa[head[y]];
end;
end;
if deep[x]<=deep[y] then ans:=maxx(ans,qmax(xtr[ck],dfn[x],dfn[y]))
else ans:=maxx(ans,qmax(xtr[ck],dfn[y],dfn[x]));
writeln(ans);
end;
end;
end;
end.