#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#pragma comment(linker, "/STACK:10240000000,10240000000")//手动开大栈区
#define lson rt*2
#define rson rt*2+1
#define mid (l+r)/2
using namespace std;
const int N=100050;
typedef long long ll;
int head[N],to[N*2],next[N*2],fa[N][35],cnt;
void add(int f,int t)
{
next[++cnt]=head[f];
to[cnt]=t;
head[f]=cnt;
}
//
int n,q,a,b,c;
ll d;
//
int son[N],size[N],dep[N];
void dfs1(int rt)
{
size[rt]=1;
int flag=0;
for(int i=head[rt];i!=-1;i=next[i])
{
dep[to[i]]=dep[rt]+1;
dfs1(to[i]);
size[rt]+=size[to[i]];
if(size[to[i]]>flag)
flag=size[to[i]],son[rt]=to[i];
}
}
int zhe[N],fan[N],mx[N],top[N],num;
void dfs2(int rt,int root)
{
top[rt]=root;
zhe[rt]=++num;
fan[num]=rt;
if(son[rt])
dfs2(son[rt],root);
for(int i=head[rt];i!=-1;i=next[i])
if(to[i]!=son[rt])
dfs2(to[i],to[i]);
mx[rt]=num;
}
//
void init()
{
for(int j=1;j<=30;j++)
for(int i=1;i<=n;i++)
if(fa[i][j-1]!=0)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
int er[31]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824};
int lca(int u,int v)
{
if(dep[u]<dep[v])
swap(u,v);
int x=dep[u]-dep[v];
for(int i=30;i>=0;i--)
{
if(x>=er[i])
u=fa[u][i],x-=er[i];
}
if(u==v)
return u;
for(int i=31;i>=0;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
struct node
{
ll sum,flag;
}tree[4*N];
void pushup(int rt)
{
tree[rt].sum=tree[lson].sum+tree[rson].sum;
}
void pushdown(int rt,int l,int r)
{
if(!tree[rt].flag)
return ;
tree[lson].sum+=(mid-l+1)*tree[rt].flag;
tree[rson].sum+=(r-mid)*tree[rt].flag;
tree[lson].flag+=tree[rt].flag;
tree[rson].flag+=tree[rt].flag;
tree[rt].flag=0;
}
void ins(int rt,int l,int r,int L,int R,ll x)
{
if(l==L&&r==R)
{
tree[rt].sum+=(r-l+1)*x;
tree[rt].flag+=x;
return ;
}
pushdown(rt,l,r);
if(mid>=R)
ins(lson,l,mid,L,R,x);
else if(mid<L)
ins(rson,mid+1,r,L,R,x);
else
ins(lson,l,mid,L,mid,x),ins(rson,mid+1,r,mid+1,R,x);
pushup(rt);
}
void chang(int u,int v,ll x)
{
int aim=lca(u,v);
if(u==v)
{
ins(1,1,n,zhe[u],zhe[u],x);
return ;
}
int cnt1=0;
while(u!=aim)
{
if(dep[top[u]]>dep[aim])
ins(1,1,n,zhe[top[u]],zhe[u],x),u=fa[top[u]][0];
else
ins(1,1,n,zhe[aim],zhe[u],x),u=aim,cnt1++;
}
while(v!=aim)
{
if(dep[top[v]]>dep[aim])
ins(1,1,n,zhe[top[v]],zhe[v],x),v=fa[top[v]][0];
else
ins(1,1,n,zhe[aim],zhe[v],x),v=aim,cnt1++;
}
if(cnt1==0)
ins(1,1,n,zhe[aim],zhe[aim],x);
else if(cnt==2)
ins(1,1,n,zhe[aim],zhe[aim],-x);
}
ll query(int rt,int l,int r,int L,int R)
{
if(l==L&&r==R)
return tree[rt].sum;
pushdown(rt,l,r);
if(mid>=R)
return query(lson,l,mid,L,R);
else if(mid<L)
return query(rson,mid+1,r,L,R);
else
return query(lson,l,mid,L,mid)+query(rson,mid+1,r,mid+1,R);
}
char f[55];
int main()
{
// freopen("tree.in","r",stdin);
// freopen("tree.ans","w",stdout);
memset(head,-1,sizeof(head));
scanf("%d",&n);
for(int i=1;i<n;i++)
scanf("%d%d",&a,&b),add(a+1,b+1),fa[b+1][0]=a+1;
init();
dfs1(1);
dfs2(1,1);
scanf("%d",&q);
while(q--)
{
scanf("%s",f);
if(f[0]=='A')
{
scanf("%d%d%lld",&b,&c,&d);
chang(b+1,c+1,d);
}
else
scanf("%d",&b),printf("%lld\n",query(1,1,n,zhe[b+1],mx[b+1]));
}
fclose(stdin);
fclose(stdout);
return 0;
}
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdio.h>
#define lson rt*2
#define rson rt*2+1
#define mid (l+r)/2
using namespace std;
const int N=100050;
int n;
int head[N],to[N*2],next[2*N],v2[2*N],v1[2*N],id[2*N],fan[N],cnt;
void add(int f,int t,int val,int hao)
{
to[++cnt]=t;
id[cnt]=hao;
v1[cnt]=val;
next[cnt]=head[f];
head[f]=cnt;
}
int a,b,c;
int size[N],son[N];
int fa[N][25];
int s[25],dep[N];
void dfs1(int x)
{
dep[x]=dep[fa[x][0]]+1;
size[x]=1;
for(int i=1;i<=16;i++)
{
if(s[i]>=dep[x])
break;
fa[x][i]=fa[fa[x][i-1]][i-1];
}
for(int i=head[x];i!=-1;i=next[i])
{
if(to[i]==fa[x][0])
continue;
fa[to[i]][0]=x;
fan[id[i]]=to[i];
v2[to[i]]=v1[i];
dfs1(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]])
son[x]=to[i];
}
}
int zhe[N],top[N],num;
void dfs2(int x,int root)
{
zhe[x]=++num;
top[x]=root;
if(son[x])
dfs2(son[x],root);
for(int i=head[x];i!=-1;i=next[i])
if(to[i]!=son[x]&&to[i]!=fa[x][0])
dfs2(to[i],to[i]);
}
int lca(int u,int v)
{
if(dep[u]<dep[v])
swap(u,v);
int cha=dep[u]-dep[v];
for(int i=16;i>=0;i--)
if(cha&s[i])
u=fa[u][i];
if(u==v)
return v;
for(int i=16;i>=0;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
struct node
{
int mx,flag,flah;
}tree[N*8];
void pushup(int rt)
{
tree[rt].mx=max(tree[lson].mx,tree[rson].mx);
}
void pushdown(int rt,int l,int r)
{
if(!tree[rt].flag&&tree[rt].flah==-1)
return;
if(l==r)
return ;
if(tree[rt].flah!=-1)
{
tree[lson].flag=tree[rson].flag=0;
tree[lson].flah=tree[rson].flah=tree[rt].flah;
tree[lson].mx=tree[rson].mx=tree[rt].flah;
tree[rt].flah=-1;
}
tree[lson].flag+=tree[rt].flag;
tree[rson].flag+=tree[rt].flag;
tree[lson].mx+=tree[rt].flag;
tree[rson].mx+=tree[rt].flag;
tree[rt].flag=0;
}
void ins1(int rt,int l,int r,int pos,int val)
{
pushdown(rt,l,r);
if(l==r)
{
tree[rt].mx=val;
return ;
}
if(mid<pos)
ins1(rson,mid+1,r,pos,val);
if(mid>=pos)
ins1(lson,l,mid,pos,val);
pushup(rt);
}
void ins2(int rt,int l,int r,int L,int R,int val)
{
pushdown(rt,l,r);
if(l==L&&r==R)
{
tree[rt].flag+=val;
tree[rt].mx+=val;
return ;
}
if(mid>=R)
ins2(lson,l,mid,L,R,val);
else if(mid<L)
ins2(rson,mid+1,r,L,R,val);
else
ins2(lson,l,mid,L,mid,val),ins2(rson,mid+1,r,mid+1,R,val);
pushup(rt);
}
void ins3(int rt,int l,int r,int L,int R,int val)
{
pushdown(rt,l,r);
if(l==L&&r==R)
{
tree[rt].flah=val;
tree[rt].flag=0;
tree[rt].mx=val;
return ;
}
if(mid>=R)
ins3(lson,l,mid,L,R,val);
else if(mid<L)
ins3(rson,mid+1,r,L,R,val);
else
ins3(lson,l,mid,L,mid,val),ins3(rson,mid+1,r,mid+1,R,val);
pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
pushdown(rt,l,r);
if(l==L&&r==R)
return tree[rt].mx;
if(mid>=R)
return query(lson,l,mid,L,R);
else if(mid<L)
return query(rson,mid+1,r,L,R);
else
return max(query(lson,l,mid,L,mid),query(rson,mid+1,r,mid+1,R));
}
void in1(int u,int v,int val)
{
while(top[u]!=top[v])
{
ins2(1,1,n,zhe[top[u]],zhe[u],val);
u=fa[top[u]][0];
}
if(zhe[v]+1<=zhe[u])
ins2(1,1,n,zhe[v]+1,zhe[u],val);
}
void in2(int u,int v,int val)
{
while(top[u]!=top[v])
{
ins3(1,1,n,zhe[top[u]],zhe[u],val);
u=fa[top[u]][0];
}
if(zhe[v]+1<=zhe[u])
ins3(1,1,n,zhe[v]+1,zhe[u],val);
}
int qu(int u,int v)
{
int res=0;
while(top[u]!=top[v])
{
res=max(query(1,1,n,zhe[top[u]],zhe[u]),res);
u=fa[top[u]][0];
}
if(zhe[v]+1<=zhe[u])
res=max(query(1,1,n,zhe[v]+1,zhe[u]),res);
return res;
}
char cc[10];
int x,y;
int main()
{
memset(head,-1,sizeof(head));
s[0]=1;
for(int i=1;i<=16;i++)
s[i]=s[i-1]*2;
scanf("%d",&n);
for(int i=1;i<n;i++)
scanf("%d%d%d",&a,&b,&c),add(a,b,c,i),add(b,a,c,i);
dfs1(1);
dfs2(1,1);
for(int i=2;i<=n;i++)
ins1(1,1,n,zhe[i],v2[i]);
while(1)
{
scanf("%s",cc);
if(cc[0]=='S')
break;
else if(cc[0]=='A')
{
scanf("%d%d%d",&a,&b,&c);
int f=lca(a,b);
if(f!=a) in1(a,f,c);
if(f!=b) in1(b,f,c);
}
else if(cc[0]=='M')
{
scanf("%d%d",&a,&b);
int f=lca(a,b);
int res=0;
if(f!=a) res=max(qu(a,f),res);
if(f!=b) res=max(qu(b,f),res);
printf("%d\n",res);
}
else if(cc[0]=='C'&&cc[1]=='o')
{
scanf("%d%d%d",&a,&b,&c);
int f=lca(a,b);
if(f!=a) in2(a,f,c);
if(f!=b) in2(b,f,c);
}
else if(cc[0]=='C'&&cc[1]=='h')
{
scanf("%d%d",&a,&b);
ins1(1,1,n,zhe[fan[a]],b);
}
}
}
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#define lson rt*2
#define rson rt*2+1
#define mid (l+r)/2
using namespace std;
const int N=100050;
typedef long long ll;
int m,n;
int head[N],next[2*N],to[2*N],cnt;
void add(int f,int t)
{
to[++cnt]=t;
next[cnt]=head[f];
head[f]=cnt;
}
ll v[N];
int a,b;
ll c;
struct node
{
ll sum,flag;
}tree[N*4];
ll size[N];
int son[N],fa[N];
void dfs1(int rt,int last)
{
ll flag=0;
size[rt]=1;
for(int i=head[rt];i!=-1;i=next[i])
{
if(to[i]==last)
continue;
fa[to[i]]=rt;
dfs1(to[i],rt);
size[rt]+=size[to[i]];
if(size[to[i]]>flag)
flag=size[to[i]],son[rt]=to[i];
}
}
int num,fan[N],zhe[N],top[N],mx[N];
ll vl[N];
void dfs2(int rt,int root)
{
zhe[rt]=++num;
fan[num]=rt;
vl[num]=v[rt];
top[rt]=root;
if(son[rt])
dfs2(son[rt],root);
for(int i=head[rt];i!=-1;i=next[i])
if(to[i]!=fa[rt]&&to[i]!=son[rt])
dfs2(to[i],to[i]);
mx[rt]=num;
}
void pushup(int rt)
{
tree[rt].sum=tree[lson].sum+tree[rson].sum;
}
void pushdown(int rt,int l,int r)
{
tree[lson].sum+=(mid-l+1)*tree[rt].flag;
tree[rson].sum+=(r-mid)*tree[rt].flag;
tree[lson].flag+=tree[rt].flag;
tree[rson].flag+=tree[rt].flag;
tree[rt].flag=0;
}
void build(int rt,int l,int r)
{
if(l==r)
{
tree[rt].sum=vl[l];
return ;
}
build(lson,l,mid);
build(rson,mid+1,r);
pushup(rt);
}
void ins(int rt,int l,int r,int L,int R,ll x)
{
if(l==L&&r==R)
{
tree[rt].sum+=(r-l+1)*x;
tree[rt].flag+=x;
return ;
}
pushdown(rt,l,r);
if(mid<L)
ins(rson,mid+1,r,L,R,x);
else if(mid>=R)
ins(lson,l,mid,L,R,x);
else
ins(lson,l,mid,L,mid,x),ins(rson,mid+1,r,mid+1,R,x);
pushup(rt);
}
ll query(int rt,int l,int r,int L,int R)
{
if(l==L&&r==R)
return tree[rt].sum;
pushdown(rt,l,r);
if(R<=mid)
return query(lson,l,mid,L,R);
else if(mid<L)
return query(rson,mid+1,r,L,R);
else
return query(lson,l,mid,L,mid)+query(rson,mid+1,r,mid+1,R);
}
ll getans(int x)
{
ll ans=0;
while(x)
{
ans+=query(1,1,n,zhe[top[x]],zhe[x]);
x=fa[top[x]];
}
return ans;
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&v[i]);
for(int i=1;i<n;i++)
scanf("%d%d",&a,&b),add(a,b),add(b,a);
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&a);
if(a==1)
scanf("%d%lld",&b,&c),ins(1,1,n,zhe[b],zhe[b],c);
else if(a==2)
scanf("%d%lld",&b,&c),ins(1,1,n,zhe[b],mx[b],c);
else
scanf("%d",&b),printf("%lld\n",getans(b));
}
}
清华大佬gconeice的题解:
显然,暴力求解的复杂度是无法承受的。
考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案。观察到,深度其实就是上面有几个已标记了的点(包括自身)。所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r 之间的点询问他们到根路径上的点权和。仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆。也就是说我们可以对于 l 到 r 之间的点 i,将 i 到根的路径上的点全部 +1, 转而询问 z 到根的路径上的点(包括自身)的权值和就是这个询问的答案。把询问差分下,也就是用 [1, r] − [1, l − 1] 来计算答案,那么现在我们就有一个明显的解法。从 0 到 n − 1 依次插入点 i,即将 i 到根的路径上的点全部+1。离线询问答案即可。我们现在需要一个数据结构来维护路径加和路径求和,显然树链剖分或LCT 均可以完成这个任务。树链剖分的复杂度为 O((n + q)· log n · log n),LCT的复杂度为 O((n + q)· log n),均可以完成任务。至此,题目已经被我们完美解决。(摘自 hzwer.com)
实在是太妙了啊啊啊在下不得不orz
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<vector>
#define lson rt*2
#define rson rt*2+1
#define mid (l+r)/2
using namespace std;
const int N=50050;
const int mo=201314;
int ans[N];
int n,q,num;
int l,r,z;
struct state
{
int loc,zz;
};
vector<state> jan[N],jia[N];
int head[N],to[N],next[N],cnt;
void add(int f,int t)
{
to[++cnt]=t;
next[cnt]=head[f];
head[f]=cnt;
}
int fa[N];
int size[N],son[N],zhe[N],dui[N],top[N];
void dfs1(int x)
{
size[x]=1;
int flag=0;
for(int i=head[x];i!=-1;i=next[i])
{
dfs1(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>flag)
{
flag=size[to[i]];
son[x]=to[i];
}
}
}
void dfs2(int x,int root)
{
zhe[x]=++num;
dui[num]=x;
top[x]=root;
if(son[x])
dfs2(son[x],root);
for(int i=head[x];i!=-1;i=next[i])
if(to[i]!=son[x])
dfs2(to[i],to[i]);
}
struct node
{
int sum;
int flag;
}tree[N*4];
void pushup(int rt)
{
tree[rt].sum=(tree[lson].sum+tree[rson].sum)%mo;
}
void pushdown(int rt,int l,int r)
{
if(!tree[rt].flag)
return ;
tree[lson].flag+=tree[rt].flag;
tree[rson].flag+=tree[rt].flag;
tree[lson].sum=(tree[lson].sum+(tree[rt].flag*(mid-l+1))%mo)%mo;
tree[rson].sum=(tree[rson].sum+(tree[rt].flag*(r-mid))%mo)%mo;
tree[rt].flag=0;
}
void ins(int rt,int l,int r,int L,int R)
{
if(l==L&&r==R)
{
tree[rt].sum=(tree[rt].sum+(r-l+1))%mo;
tree[rt].flag+=1;
return ;
}
pushdown(rt,l,r);
if(mid>=R)
ins(lson,l,mid,L,R);
else if(mid<L)
ins(rson,mid+1,r,L,R);
else
ins(lson,l,mid,L,mid),ins(rson,mid+1,r,mid+1,R);
pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if(l==L&&r==R)
return tree[rt].sum;
pushdown(rt,l,r);
if(mid>=R)
return query(lson,l,mid,L,R)%mo;
else if(mid<L)
return query(rson,mid+1,r,L,R)%mo;
else
return (query(lson,l,mid,L,mid)+query(rson,mid+1,r,mid+1,R))%mo;
}
void chang(int x)
{
int d=x;
while(d)
{
ins(1,1,n,zhe[top[d]],zhe[d]);
d=fa[top[d]];
}
}
int get(int x)
{
int res=0;
int d=x;
while(d)
{
res=(res+query(1,1,n,zhe[top[d]],zhe[d])%mo)%mo;
d=fa[top[d]];
}
return res;
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&q);
for(int i=2;i<=n;i++)
scanf("%d",&fa[i]),fa[i]++,add(fa[i],i);
for(int i=1;i<=q;i++)
scanf("%d%d%d",&l,&r,&z),jia[r+1].push_back((state){i,z+1}),jan[l].push_back((state){i,z+1});
dfs1(1);
dfs2(1,1);
for(int i=1;i<=n;i++)
{
chang(i);
for(int j=0;j<jan[i].size();j++)
ans[jan[i][j].loc]=(ans[jan[i][j].loc]-get(jan[i][j].zz)+mo)%mo;
for(int j=0;j<jia[i].size();j++)
ans[jia[i][j].loc]=(get(jia[i][j].zz)+ans[jia[i][j].loc])%mo;
}
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
}
bzoj3531
题意:
一棵树,每个树有一种颜色和一个权值,现在有四种操作:
1.改变一个节点的权值
2.改变一个节点的颜色
3.询问从u到v(保证u,v颜色相同)这条路上与uv颜色相同的点的权值总和
4.询问从u到v(也保证u,v颜色相同)这条路上与uv颜色相同的点的权值最大值
要点:
1.怎么判断是不是颜色相同?
我学会了特殊的开多个线段树的技巧,我会假装四处看风景!
好吧不是什么特殊的,就是这个题需要为每个宗教开一个线段树,而我终于掌握了这种技巧。。。
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>
#define mid (l+r)/2
using namespace std;
const int N=100050;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,a,b;
int head[N],to[2*N],next[2*N],cnt;
void add(int f,int t)
{
to[++cnt]=t;
next[cnt]=head[f];
head[f]=cnt;
}
int s[N];
int T[N],w[N];
int fa[N][25];
int son[N],size[N];
int dep[N];
void dfs1(int x)
{
dep[x]=dep[fa[x][0]]+1;
for(int i=1;i<=16;i++)
{
if(s[i]>dep[x])
break;
fa[x][i]=fa[fa[x][i-1]][i-1];
}
size[x]=1;
int flag=0;
for(int i=head[x];i!=-1;i=next[i])
{
if(to[i]==fa[x][0])
continue;
fa[to[i]][0]=x;
dfs1(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>flag)
flag=size[to[i]],son[x]=to[i];
}
}
int zhe[N],top[N],num;
void dfs2(int x,int root)
{
zhe[x]=++num;
top[x]=root;
if(son[x])
dfs2(son[x],root);
for(int i=head[x];i!=-1;i=next[i])
if(to[i]!=son[x]&&to[i]!=fa[x][0])
dfs2(to[i],to[i]);
}
int lca(int u,int v)
{
if(dep[u]<dep[v])
swap(u,v);
int cha=dep[u]-dep[v];
for(int i=16;i>=0;i--)
if(cha&s[i])
u=fa[u][i];
if(u==v)
return u;
for(int i=16;i>=0;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
struct node
{
int sum,mx,ls,rs;
}tree[100*N];
void pushup(int rt)
{
tree[rt].sum=tree[tree[rt].ls].sum+tree[tree[rt].rs].sum;
tree[rt].mx=max(tree[tree[rt].ls].mx,tree[tree[rt].rs].mx);
}
int tot;
int root[N];
void ins(int &rt,int l,int r,int pos,int val)
{
if(!rt)
rt=++tot;
if(l==r)
{
tree[rt].mx=tree[rt].sum=val;
return ;
}
if(pos<=mid)
ins(tree[rt].ls,l,mid,pos,val);
else
ins(tree[rt].rs,mid+1,r,pos,val);
pushup(rt);
}
int querysum(int rt,int l,int r,int L,int R)
{
if(!rt) return 0;
if(l==L&&r==R)
return tree[rt].sum;
if(mid>=R)
return querysum(tree[rt].ls,l,mid,L,R);
else if(mid<L)
return querysum(tree[rt].rs,mid+1,r,L,R);
else
return querysum(tree[rt].ls,l,mid,L,mid)+querysum(tree[rt].rs,mid+1,r,mid+1,R);
}
int querymax(int rt,int l,int r,int L,int R)
{
if(!rt) return 0;
if(l==L&&r==R)
return tree[rt].mx;
if(mid>=R)
return querymax(tree[rt].ls,l,mid,L,R);
else if(mid<L)
return querymax(tree[rt].rs,mid+1,r,L,R);
else
return max(querymax(tree[rt].ls,l,mid,L,mid),querymax(tree[rt].rs,mid+1,r,mid+1,R));
}
int solvesum(int u,int v,int c)
{
int res=0;
int x=u;
while(top[x]!=top[v])
{
res+=querysum(root[c],1,n,zhe[top[x]],zhe[x]);
x=fa[top[x]][0];
}
res+=querysum(root[c],1,n,zhe[v],zhe[x]);
return res;
}
int solvemax(int u,int v,int c)
{
int res=0;
int x=u;
while(top[x]!=top[v])
{
res=max(res,querymax(root[c],1,n,zhe[top[x]],zhe[x]));
x=fa[top[x]][0];
}
res=max(res,querymax(root[c],1,n,zhe[v],zhe[x]));
return res;
}
int city1,city2,city,zong;
int main()
{
s[0]=1;for(int i=1;i<=16;i++)s[i]=(s[i-1]<<1);
memset(head,-1,sizeof(head));
n=read();
m=read();
for(int i=1;i<=n;i++)
w[i]=read(),T[i]=read();
for(int i=1;i<n;i++)
a=read(),b=read(),add(a,b),add(b,a);
dfs1(1);
dfs2(1,1);
for(int i=1;i<=n;i++)
ins(root[T[i]],1,n,zhe[i],w[i]);
for(int i=1;i<=m;i++)
{
char cc[4];
scanf("%s",cc);
if(cc[0]=='C')
{
if(cc[1]=='C')
{
city=read();
zong=read();
ins(root[T[city]],1,n,zhe[city],0);
T[city]=zong;
ins(root[T[city]],1,n,zhe[city],w[city]);
}
else
{
city=read();
zong=read();
ins(root[T[city]],1,n,zhe[city],zong);
w[city]=zong;
}
}
else
{
if(cc[1]=='S')
{
city1=read();
city2=read();
int f=lca(city1,city2);
printf("%d\n",solvesum(city1,f,T[city1])+solvesum(city2,f,T[city2])-(T[f]==T[city1])*w[f]);
}
else if(cc[1]=='M')
{
city1=read();
city2=read();
int f=lca(city1,city2);
printf("%d\n",max(solvemax(city1,f,T[city1]),solvemax(city2,f,T[city2])));
}
}
}
}