树根一定要处理QAQ
#include <cstdio>
using namespace std;
int read()
{
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return f*x;
}
const int N=1e5+5;
int n,m,father[N],son[N],dep[N],size[N],top[N];
int tre[N*4],sum[N*4],rev[N],seg[N],num,a[N];
int had[N],to[N*2],nxt[N*2],p,a1,b1;
char c[N];
int max(int x,int y)
{
if(x>y) return x;
return y;
}
void swap(int &x,int &y)
{
x^=y; y^=x; x^=y;
}
void add_edge(int x,int y)
{
nxt[++p]=had[x];
to[p]=y;
had[x]=p;
}
void deal_first(int u,int fa)
{
father[u]=fa;
size[u]=1;
dep[u]=dep[fa]+1;
for(int i=had[u];i;i=nxt[i])
{
int v=to[i];
if(v==fa) continue;
deal_first(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
void deal_second(int u,int fa)
{
if(son[u])
{
seg[son[u]]=++num;
rev[num]=son[u];
top[son[u]]=top[u];
deal_second(son[u],u);
}
for(int i=had[u];i;i=nxt[i])
{
int v=to[i];
if(top[v]) continue;
seg[v]=++num;
rev[num]=v;
top[v]=v;
deal_second(v,u);
}
}
void build(int k,int l,int r)
{
if(l==r)
{
tre[k]=sum[k]=a[rev[l]];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build((k<<1)+1,mid+1,r);
sum[k]=sum[k<<1]+sum[(k<<1)+1];
tre[k]=max(tre[k<<1],tre[(k<<1)+1]);
}
void change(int k,int l,int r,int x,int v)
{
if(l>x||r<x) return;
if(l==r&&l==x)
{
tre[k]=sum[k]=v;
return;
}
int mid=(l+r)>>1;
change(k<<1,l,mid,x,v);
change((k<<1)+1,mid+1,r,x,v);
sum[k]=sum[k<<1]+sum[(k<<1)+1];
tre[k]=max(tre[k<<1],tre[(k<<1)+1]);
}
int query_max(int k,int l,int r,int x,int y)
{
if(r<x||l>y) return -50000;
if(l>=x&&r<=y) return tre[k];
int mid=(l+r)>>1;
return max(query_max(k<<1,l,mid,x,y),query_max((k<<1)+1,mid+1,r,x,y));
}
void ask_max(int x,int y)
{
int fax=top[x],fay=top[y],ans=-50000;
while(fax!=fay)
{
if(dep[fax]<dep[fay])
{
swap(x,y);
swap(fax,fay);
}
ans=max(ans,query_max(1,1,num,seg[fax],seg[x]));
x=father[fax]; fax=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
ans=max(ans,query_max(1,1,num,seg[x],seg[y]));
printf("%d\n",ans);
}
int query_sum(int k,int l,int r,int x,int y)
{
if(r<x||l>y) return 0;
if(l>=x&&r<=y) return sum[k];
int mid=(l+r)>>1,ret=0;
ret+=query_sum(k<<1,l,mid,x,y);
ret+=query_sum((k<<1)+1,mid+1,r,x,y);
return ret;
}
void ask_sum(int x,int y)
{
int fax=top[x],fay=top[y],ans=0;
while(fax!=fay)
{
if(dep[fax]<dep[fay])
{
swap(x,y);
swap(fax,fay);
}
ans+=query_sum(1,1,num,seg[fax],seg[x]);
x=father[fax]; fax=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
ans+=query_sum(1,1,num,seg[x],seg[y]);
printf("%d\n",ans);
}
int main()
{
n=read();
for(int i=1;i<n;i++)
{
a1=read(); b1=read();
add_edge(a1,b1);
add_edge(b1,a1);
}
for(int i=1;i<=n;i++) a[i]=read();
deal_first(1,0);
num++;
seg[1]=top[1]=rev[1]=1;
deal_second(1,0);
build(1,1,num);
m=read();
while(m--)
{
scanf("%s",c);
a1=read(); b1=read();
if(c[1]=='H') change(1,1,num,seg[a1],b1);
if(c[1]=='M') ask_max(a1,b1);
if(c[1]=='S') ask_sum(a1,b1);
}
return 0;
}