题目链接,直接 LCT 就好,注意取模,还有数据很强, 510612 会爆 int
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <iostream>
#include <algorithm>
template<class Num>void read(Num &x)
{
char c; int flag = 1;
while((c = getchar()) < '0' || c > '9')
if(c == '-') flag *= -1;
x = c - '0';
while((c = getchar()) >= '0' && c <= '9')
x = (x<<3) + (x<<1) + (c-'0');
x *= flag;
return;
}
template<class Num>void write(Num x)
{
if(!x) {putchar('0');return;}
if(x < 0) putchar('-'), x = -x;
static char s[20];int sl = 0;
while(x) s[sl++] = x%10 + '0',x /= 10;
while(sl) putchar(s[--sl]);
}
const int maxn = 1e5 + 50, maxq = maxn;
const int INF = 0x3f3f3f3f, Nya = -1;
const int Mod = 51061;
int n, m, q;
unsigned int val[maxn], sum[maxn];
int size[maxn];
unsigned int mul[maxn], add[maxn];
namespace LCT
{
int c[maxn][2], fa[maxn];
int rev[maxn];
void update(int x)
{
sum[x] = (sum[c[x][0]] + sum[c[x][1]] + val[x]) % Mod;
size[x] = size[c[x][0]] + size[c[x][1]] + 1;
}
void _mul(int v,int x)
{
val[v] = (val[v] * x) % Mod;
sum[v] = (sum[v] * x) % Mod;
mul[v] = (mul[v] * x) % Mod;
add[v] = (add[v] * x) % Mod;
}
void _add(int v,int x)
{
val[v] = (val[v] + x) % Mod;
sum[v] = (sum[v] + x * size[v]) % Mod;
add[v] = (add[v] + x) % Mod;
}
void pushdown(int x)
{
int v;
if(rev[x])
{
rev[c[x][0]] ^= 1;
rev[c[x][1]] ^= 1;
std::swap(c[x][0], c[x][1]);
rev[x] = 0;
}
if(mul[x] != 1)
{
if(c[x][0]) _mul(c[x][0], mul[x]);
if(c[x][1]) _mul(c[x][1], mul[x]);
mul[x] = 1;
}
if(add[x])
{
if(c[x][0]) _add(c[x][0], add[x]);
if(c[x][1]) _add(c[x][1], add[x]);
add[x] = 0;
}
}
bool isroot(int x)
{
return x != c[fa[x]][0] && x != c[fa[x]][1];
}
void rotate(int x)
{
int y = fa[x], z = fa[y], i, j;
pushdown(y), pushdown(x);
j = (c[z][1] == y), i = (c[y][1] == x);
if(!isroot(y)) c[z][j] = x;
else fa[x] = fa[y], fa[y] = 0;
if(c[x][i^1]) fa[c[x][i^1]] = y;
fa[x] = z, fa[y] = x;
c[y][i] = c[x][i^1], c[x][i^1] = y;
update(y), update(x);
}
void Splay(int v)
{
int g = fa[v], h = fa[g];
pushdown(v);
while(!isroot(v))
{
if(!isroot(g))
{
if((c[h][1] == g)^(c[g][1] == v))
rotate(v);
else
rotate(g);
}
rotate(v), g = fa[v], h = fa[g];
}
update(v);
}
void access(int v)
{
int u = v, e = v;
v = 0;
while(u)
{
Splay(u);
int &t = c[u][1];
t = v, update(u);
v = u, u = fa[u];
}
Splay(e);
}
void makeroot(int v)
{
access(v);
rev[v] ^= 1;
}
void join(int v,int u)
{
makeroot(v);
fa[v] = u;
access(v);
}
void cut(int v,int u)
{
makeroot(v);
access(u);
c[u][0] = fa[v] = 0;
}
}
void init()
{
int u, v;
read(n), read(q);
for(int i = 1; i <= n; i++)
sum[i] = val[i] = mul[i] = size[i] = 1;
for(int i = 1; i < n; i++)
read(u), read(v), LCT::join(u, v);
}
void solve()
{
char str[5];
int u, v, x, y;
while(q--)
{
scanf("%s", str);
if(str[0] == '+')
{
read(u), read(v), read(x);
LCT::makeroot(u), LCT::access(v), LCT::_add(v, x);
}
else if(str[0] == '-')
{
read(u), read(v), read(x), read(y);
LCT::cut(u, v), LCT::join(x, y);
}
else if(str[0] == '*')
{
read(u), read(v), read(x);
LCT::makeroot(u), LCT::access(v), LCT::_mul(v, x);
}
else if(str[0] == '/')
{
read(u), read(v);
LCT::makeroot(u), LCT::access(v);
write(sum[v]), puts("");
}
else
std::cerr << "error!";
}
}
int main()
{
freopen("nt2012_wym_tree.in","r",stdin);
freopen("nt2012_wym_tree.out","w",stdout);
init();
solve();
fclose(stdin);
fclose(stdout);
return 0;
}