傻逼题无脑码了20几分钟就码完啦= =
结果顺手把y打成了x就WA了一发。。。
unsigned int 比 long long快很多啊
#include<iostream>
#include<cstdio>
#define ll unsigned int
#define P 51061
#define N 100005
using namespace std;
int n,Q;
int rev[N],size[N],stack[N],fa[N],tree[N][2];
ll val[N],sum[N],tag_mul[N],tag_add[N];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline bool isroot(int k)
{
return tree[fa[k]][0]!=k&&tree[fa[k]][1]!=k;
}
inline void pushup(int k)
{
size[k]=size[tree[k][0]]+size[tree[k][1]]+1;
sum[k]=(sum[tree[k][0]]+sum[tree[k][1]]+val[k])%P;
}
inline void pushdown(int k)
{
if (rev[k])
{
rev[k]^=1; rev[tree[k][0]]^=1; rev[tree[k][1]]^=1;
swap(tree[k][0],tree[k][1]);
}
if (tag_mul[k]==1&&tag_add[k]==0) return;
val[tree[k][0]]=(val[tree[k][0]]*tag_mul[k]+tag_add[k])%P;
sum[tree[k][0]]=(sum[tree[k][0]]*tag_mul[k]+tag_add[k]*size[tree[k][0]])%P;
tag_mul[tree[k][0]]=(tag_mul[k]*tag_mul[tree[k][0]])%P;
tag_add[tree[k][0]]=(tag_mul[k]*tag_add[tree[k][0]]+tag_add[k])%P;
val[tree[k][1]]=(val[tree[k][1]]*tag_mul[k]+tag_add[k])%P;
sum[tree[k][1]]=(sum[tree[k][1]]*tag_mul[k]+tag_add[k]*size[tree[k][1]])%P;
tag_mul[tree[k][1]]=(tag_mul[k]*tag_mul[tree[k][1]])%P;
tag_add[tree[k][1]]=(tag_mul[k]*tag_add[tree[k][1]]+tag_add[k])%P;
tag_mul[k]=1; tag_add[k]=0;
}
inline void rotate(int x)
{
int y=fa[x],z=fa[y],l=tree[y][1]==x,r=l^1;
if (!isroot(y)) tree[z][tree[z][1]==y]=x;
fa[x]=z; fa[y]=x; fa[tree[x][r]]=y;
tree[y][l]=tree[x][r]; tree[x][r]=y;
pushup(y); pushup(x);
}
inline void splay(int x)
{
int top=0;
stack[++top]=x;
for (int i=x;!isroot(i);i=fa[i]) stack[++top]=fa[i];
for (int i=top;i;i--) pushdown(stack[i]);
while (!isroot(x))
{
int y=fa[x],z=fa[y];
if (!isroot(y))
{
if (tree[y][0]==x^tree[z][0]==y) rotate(x); else rotate(y);
}
rotate(x);
}
}
inline void access(int x)
{
for (int t=0;x;t=x,x=fa[x])
splay(x),tree[x][1]=t,pushup(x);
}
inline void rever(int x)
{
access(x); splay(x); rev[x]^=1;
}
inline void link(int x,int y)
{
rever(x); fa[x]=y;
}
inline void cut(int x,int y)
{
rever(x); access(y); splay(y);
tree[y][0]=fa[x]=0; pushup(y);
}
inline void change(int x,int y,int mul,int add)
{
rever(x); access(y); splay(y);
val[y]=(val[y]*mul+add)%P;
sum[y]=(sum[y]*mul+size[y]*add)%P;
tag_mul[y]=(tag_mul[y]*mul)%P;
tag_add[y]=(tag_add[y]*mul+add)%P;
}
inline int query(int x,int y)
{
rever(x); access(y); splay(y);
return sum[y];
}
int main()
{
n=read(); Q=read();
for (int i=1;i<=n;i++) val[i]=sum[i]=size[i]=tag_mul[i]=1;
for (int i=1;i<n;i++)
{
int u=read(),v=read();
link(u,v);
}
while (Q--)
{
char opt[5];
scanf("%s",opt);
int u=read(),v=read(),u0,v0,c;
switch (opt[0])
{
case '+':
c=read();
change(u,v,1,c);
break;
case '-':
u0=read(); v0=read();
cut(u,v); link(u0,v0);
break;
case '*':
c=read();
change(u,v,c,0);
break;
case '/':
printf("%d\n",query(u,v));
break;
}
}
return 0;
}