题目>>http://codevs.cn/problem/2460/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 1e6 + 5;
typedef long long ll;
ll n,a,b,num[MAXN],q,firs[MAXN],nex[MAXN],cnt = 0;
char s[15];
struct zt
{
ll f,t;
}road[MAXN];
void build(ll f,ll t)
{
road[++cnt] = (zt){f,t};
nex[cnt] = firs[f];
firs[f] = cnt;
}
ll fa[MAXN],son[MAXN],sz[MAXN],deep[MAXN];
void dfs1(ll x,ll f)
{
fa[x] = f;
deep[x] = deep[f] + 1;
sz[x] = 1;
for(int i = firs[x];i != -1;i = nex[i])
{
ll v = road[i].t;
if(v != f)
{
dfs1(v,x);
sz[x] += sz[v];
if(!son[x]||sz[v] > sz[son[x]]) son[x] = v;
}
}
}
ll intu[MAXN],top[MAXN],tot = 0;
void dfs2(ll x,ll topx)
{
top[x] = topx;
intu[x] = ++tot;
if(!son[x]) return;
dfs2(son[x],topx);
for(int i = firs[x];i != -1;i = nex[i])
{
int v = road[i].t;
if(v != fa[x]&&v != son[x])
dfs2(v,v);
}
}
struct dd
{
ll sum,maxn;
dd *lift,*right;
}tree[MAXN];
ll cc = 0;
void hs(dd *root)
{
root->sum = root->lift->sum + root->right->sum;
root->maxn = max(root->lift->maxn,root->right->maxn);
}
void build_tree(dd *root,ll l,ll r)
{
root->sum = 0;root->maxn = 0;
if(l == r)
return;
ll mid = l + r >>1;
root->right = &tree[++cc];
root->lift = &tree[++cc];
build_tree(root->lift,l,mid);
build_tree(root->right,mid + 1,r);
hs(root);
}
void change(dd *root,ll l,ll r,ll q,ll x)
{
if(l == r)
{
root->sum = root->maxn = x;
return;
}
ll mid = l + r >> 1;
if(q <= mid) change(root->lift,l,mid,q,x);
else change(root->right,mid + 1,r,q,x);
hs(root);
}
ll ask_sum(dd *root,ll l,ll r,ll ql,ll qr)
{
if(l >= ql&&qr >= r)
return root->sum;
ll mid = l + r >> 1,ans = 0;
if(ql <= mid) ans += ask_sum(root->lift,l,mid,ql,qr);
if(qr > mid) ans += ask_sum(root->right,mid + 1,r,ql,qr);
return ans;
}
ll find_sum(ll x,ll y)
{
ll xt = top[x],yt = top[y],ans = 0;
while(xt != yt)
{
if(deep[xt] < deep[yt]) swap(xt,yt),swap(x,y);
ans += ask_sum(tree,1,n,intu[xt],intu[x]);
x = fa[xt];xt = top[x];
}
if(deep[x] > deep[y]) swap(x,y);
ans += ask_sum(tree,1,n,intu[x],intu[y]);
return ans;
}
ll ask_max(dd *root,ll l,ll r,ll ql,ll qr)
{
if(l >= ql&&qr >= r)
return root->maxn;
ll mid = l + r >> 1,ans = -1e6;
if(ql <= mid) ans = max(ask_max(root->lift,l,mid,ql,qr),ans);
if(qr > mid) ans = max(ask_max(root->right,mid + 1,r,ql,qr),ans);
return ans;
}
ll find_max(ll x,ll y)
{
ll xt = top[x],yt = top[y],ans = -1e6;
while(xt != yt)
{
if(deep[xt] < deep[yt]) swap(xt,yt),swap(x,y);
ans = max(ask_max(tree,1,n,intu[xt],intu[x]),ans);
x = fa[xt];xt = top[x];
}
if(deep[x] > deep[y]) swap(x,y);
ans = max(ask_max(tree,1,n,intu[x],intu[y]),ans);
return ans;
}
int main()
{
scanf("%lld",&n);
for(int i = 1;i <= n;i ++)
firs[i] = -1;
for(int i = 1;i < n;i ++)
{
scanf("%lld%lld",&a,&b);
build(a,b);
build(b,a);
}
dfs1(1,0);
dfs2(1,1);
build_tree(tree,1,n);
for(int i = 1;i <= n; i++)
{
scanf("%lld",&a);
change(tree,1,n,intu[i],a);
}
scanf("%lld",&q);
for(int i = 1;i <= q;i ++)
{
scanf("%s%lld%lld",s,&a,&b);
if(s[0] == 'C') change(tree,1,n,intu[a],b),num[a] = b;
else if(s[1] == 'M') cout<<find_max(a,b)<<'\n';
else cout<<find_sum(a,b)<<'\n';
}
}