这题细节巨多!!!!!!
当同时维护乘法、加法标记时,根据运算先后,要先下放乘法标记。
给一个节点×v:本节点、子树和、乘法标记、加法标记均要×v。
然而改完之后还是只有5分。
56061 × 56061 = 2607225721 > 2147483647
于是int就被替换为unsigned int吧。
然后就华丽的A掉了。
我是个文明人。
#include <cstdio>
#include <algorithm>
#define N 100010
#define mod 51061
#define pa fa[x]
#define lc ch[x][0]
#define rc ch[x][1]
using namespace std;
inline char gc() {
static char now[1<<16], *S, *T;
if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;}
return *S++;
}
inline int read() {
int x = 0; char c = gc();
while(c < '0' || c > '9') c = gc();
while(c >= '0' && c <= '9') {x = x * 10 + c - 48; c = gc();}
return x;
}
namespace lct {
int ch[N][2], fa[N], rev[N], sz[N]; unsigned int w[N], sum[N], plus[N], mult[N];
inline void rever(int x) {swap(lc, rc); rev[x]^= 1;}
inline void add(int x, int v) {plus[x] = (plus[x] + v) % mod; w[x] = (w[x] + v) % mod; sum[x] = (sum[x] + sz[x] * v % mod) % mod;}
inline void tim(int x, int v) {mult[x] = mult[x] * v % mod; w[x] = w[x] * v % mod; sum[x] = sum[x] * v % mod; plus[x] = plus[x] * v % mod;}
inline void pushdn(int x) {
if(rev[x]) {if(lc) rever(lc); if(rc) rever(rc); rev[x] = 0;}
if(mult[x] != 1) {if(lc) tim(lc, mult[x]); if(rc) tim(rc, mult[x]); mult[x] = 1;}
if(plus[x]) {if(lc) add(lc, plus[x]); if(rc) add(rc, plus[x]); plus[x] = 0;}
}
inline int isroot(int x) {return ((ch[pa][0] != x) && (ch[pa][1] != x));}
void pd(int x) {if(!isroot(x)) pd(pa); pushdn(x);}
inline void update(int x) {
sz[x] = sz[lc] + sz[rc] + 1;
sum[x] = (sum[lc] + sum[rc] + w[x]) % mod;
}
inline int wh(int x) {return (ch[pa][1] == x);}
inline void rotate(int x) {
int y = fa[x], z = fa[y], c = wh(x);
if(!isroot(y)) ch[z][wh(y)] = x; fa[x] = z;
ch[y][c] = ch[x][c^1]; fa[ch[y][c]] = y;
ch[x][c^1] = y; fa[y] = x;
update(y); update(x);
}
inline void splay(int x) {
pd(x);
for(; !isroot(x); rotate(x))
if(!isroot(pa)) rotate(wh(pa) == wh(x) ? pa : x);
}
inline void access(int x) {
for(int y = 0; x; y = x, x = pa) splay(x), rc = y, update(x);
}
inline void maker(int x) {
access(x); splay(x); rever(x);
}
inline void link(int x, int y) {
maker(x); fa[x] = y;
}
inline void cut(int x, int y) {
maker(x); access(y); splay(y);
fa[x] = ch[y][0] = 0; update(y);
}
}
int n, Q;
int main() {
n = read(); Q = read();
for(int i = 1; i <= n; ++i) lct::w[i] = 1, lct::sum[i] = 1, lct::mult[i] = 1, lct::sz[i] = 1;
for(int i = 1; i < n; ++i) {int u = read(), v = read(); lct::link(u, v);}
for(int i = 1; i <= Q; ++i) {
char opt = '#';
while(opt != '+' && opt != '-' && opt != '*' && opt != '/') opt = gc();
int u = read(), v = read();
if(opt == '+') {
int c = read();
lct::maker(u); lct::access(v); lct::splay(v); lct::add(v, c);
}
if(opt == '-') {
lct::cut(u, v);
u = read(); v = read();
lct::link(u, v);
}
if(opt == '*') {
int c = read();
lct::maker(u); lct::access(v); lct::splay(v); lct::tim(v, c);
}
if(opt == '/') {
lct::maker(u); lct::access(v); lct::splay(v);
printf("%d\n", lct::sum[v]);
}
}
return 0;
}