#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
// Splay
const int MAXN = 1e5 + 10;
const long long Md = 51061;
int val[MAXN],cc[MAXN][2],fa[MAXN],siz[MAXN];
bool rev[MAXN];
long long adt[MAXN],ans[MAXN],mul[MAXN];
inline void pushUp(int x){
if(x==0) return;
ans[x]=(ans[cc[x][0]]+ans[cc[x][1]]+val[x])%Md;
siz[x]=siz[cc[x][0]]+siz[cc[x][1]]+1;
}
inline void revSplay(int x){
swap(cc[x][0],cc[x][1]),rev[x]^=1;
}
inline void addSplay(int x,int v){
(adt[x]+=v)%=Md;(ans[x]+=1ll*v*siz[x])%=Md;(val[x]+=v)%=Md;
}
inline void mulSplay(int x,int v){
(adt[x]*=v)%=Md;(mul[x]*=v)%=Md;(val[x]*=v)%=Md;(ans[x]*=v)%=Md;
}
inline void pushDown(int x){
if(mul[x]!=1){
if(cc[x][0]) mulSplay(cc[x][0],mul[x]);
if(cc[x][1]) mulSplay(cc[x][1],mul[x]);
mul[x]=1;
}
if(adt[x]){
if(cc[x][0]) addSplay(cc[x][0],adt[x]);
if(cc[x][1]) addSplay(cc[x][1],adt[x]);
adt[x]=0;
}
if(rev[x]){
if(cc[x][0]) revSplay(cc[x][0]);
if(cc[x][1]) revSplay(cc[x][1]);
rev[x]=false;
}
}
// Start - nroot
inline bool nroot(int x){
return cc[fa[x]][0]==x || cc[fa[x]][1]==x;
}
// End - nroot
inline void rtt(int x){
int y=fa[x],z=fa[y],k=(cc[y][1]==x);
if(z && nroot(y))
cc[z][cc[z][1]==y]=x;
fa[x]=z;
cc[y][k]=cc[x][!k];
if(cc[x][!k]) fa[cc[x][!k]]=y;
cc[x][!k]=y;fa[y]=x;
pushUp(y);pushUp(x);
}
vector<int> stk;
inline void splay(int x,int g=0){
int q=x;stk.push_back(q);
while(nroot(q)) stk.push_back(q=fa[q]);
while(!stk.empty()) pushDown(stk.back()),stk.pop_back();
while(nroot(x)){
int y=fa[x],z=fa[y];
if(nroot(y))
((cc[z][0]==y)^(cc[y][0]==x))?rtt(x):rtt(y);
rtt(x);
}
pushUp(x);
}
// Link Cut Tree
inline void access(int x){
for(int y=0;x;x=fa[y=x])
splay(x),cc[x][1]=y,pushUp(x);
}
inline void makeRoot(int x){
access(x);splay(x);revSplay(x);
}
inline int findRoot(int x){
access(x);splay(x);
while(cc[x][0]) pushDown(x),x=cc[x][0];
splay(x);return x;
}
inline void split(int x,int y){
makeRoot(x);access(y);splay(y);
}
//inline void link(int x,int y){
// makeRoot(x);
// if(findRoot(y)==x) return;
// fa[x]=y;pushUp(y);
//}
//inline void cut(int x,int y){
// makeRoot(x);
// if(findRoot(y)!=x || fa[y]!=x || cc[y][0]) return;
// fa[y]=cc[x][1]=0;pushUp(x);
//}
inline void link(int x,int y){
makeRoot(x);fa[x]=y;pushUp(y);
}
inline void cut(int x,int y){
split(x,y);fa[x]=cc[y][0]=0;
}
int N,M;
int main(){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++) mul[i]=siz[i]=val[i]=ans[i]=1;
for(int i=1,x,y;i<N;i++){
scanf("%d%d",&x,&y);link(x,y);
}
int x,y,z;
char typ[2];
while(M--){
scanf(" %s",typ);
if(typ[0]=='+'){
scanf("%d%d%d",&x,&y,&z);
split(x,y);addSplay(y,z);
}
else if(typ[0]=='-'){
scanf("%d%d",&x,&y);cut(x,y);
scanf("%d%d",&x,&y);link(x,y);
}
else if(typ[0]=='*'){
scanf("%d%d%d",&x,&y,&z);
split(x,y);mulSplay(y,z);
}
else{
scanf("%d%d",&x,&y);
split(x,y);printf("%lld\n",ans[y]);
}
}
return 0;
}
情况是只 AC 了最后一个点。