最后一个点 qwq.
#include <bits/stdc++.h>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#define int long long
#define ls son[u][0]
#define rs son[u][1]
#define add(x, y) x = (x + y) % MOD
#define mul(x, y) x = (x * y) % MOD
using namespace std;
const int N = 1e5 + 5, inf = 1e9 + 5, MOD = 51061;
int n, m, a[N];
namespace LCT {
int fa[N], son[N][2], s[N], siz[N], st[N], ad[N], ml[N];
bool rev[N];
inline bool isr (int u) { return son[fa[u]][0] == u || son[fa[u]][1] == u;}
inline void pushup (int u) { s[u] = (s[ls] + s[rs] + a[u]) % MOD, siz[u] = siz[ls] + siz[rs] + 1; }
inline void getrev (int u) { swap(ls, rs), rev[u] ^= 1; }
inline void getad (int u, int c) { add(s[u], c * siz[u]), add(a[u], c), add(ad[u], c); }
inline void getml (int u, int c) { mul(s[u], c), mul(a[u], c), mul(ml[u], c), mul(ad[u], c); }
inline void pushdown (int u) {
if (ml[u] != 1) getml(ls, ml[u]), getad(rs, ml[u]), ml[u] = 1;
if (ad[u]) getad(ls, ad[u]), getad(rs, ad[u]), ad[u] = 0;
if (rev[u]) {
if (ls) getrev(ls);
if (rs) getrev(rs);
rev[u] = 0;
}
}
inline void rotate (int u) {
int y = fa[u], z = fa[y], f = son[y][1] == u, g = son[u][! f];
if (isr(y)) son[z][son[z][1] == y] = u;
son[u][! f] = y, son[y][f] = g;
if (g) fa[g] = y;
fa[y] = u, fa[u] = z, pushup(y);
}
inline void splay (int u) {
int v = u, w, top = 0;
st[++ top] = v;
while (isr(v)) st[++ top] = v = fa[v];
while (top) pushdown(st[top --]);
while (isr(u)) {
v = fa[u], w = fa[v];
if (isr(v)) rotate((son[v][0] == u) ^ (son[w][0] == v) ? u : v);
rotate(u);
}
pushup(u);
}
inline void access (int u) { for (int v = 0; u; u = fa[v = u]) splay(u), rs = v, pushup(u); }
inline void makert (int u) { access(u), splay(u), getrev(u); }
inline void split (int u, int v) { makert(u), access(v), splay(v); }
inline int getrt (int u) {
access(u), splay(u);
while (ls) pushdown(u), u = ls;
splay(u); return u;
}
inline void link (int u, int v) {
makert(u);
if (getrt(v) != u) fa[u] = v;
} // void -> bool -> existed
inline void cut (int u, int v) {
makert(u);
if (getrt(v) == u && fa[v] == u && ! son[v][0])
fa[v] = rs = 0, pushup(u);
} // void -> bool -> existed
}
signed main() {
ios ::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i ++) a[i] = LCT::siz[i] = LCT::ml[i] = 1;
for (int i = 1, u, v; i < n; i ++)
cin >> u >> v, LCT::link(u, v);
for (int i = 1; i <= m; i ++) {
char opt;
int u, v, k;
cin >> opt;
if (opt == '+') {
cin >> u >> v >> k;
LCT::split(u, v), LCT::getad(v, k);
}
else if (opt == '-') {
cin >> u >> v, LCT::cut(u, v);
cin >> u >> v, LCT::link(u, v);
}
else if (opt == '*') {
cin >> u >> v >> k;
LCT::split(u, v), LCT::getml(v, k);
}
else if (opt == '/') {
cin >> u >> v;
LCT::split(u, v), cout << LCT::s[v]<<endl;
}
}
return 0;
}