lg1501
这题需要维护的比较多啊,乘法下放标记、加分下放标记、数值、和
要注意因为有乘法和加法、所以下放时应当先下放乘法、再下放加法
还有..要用long long哦,因为51061*51061超int了…
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
#define mod 51061
#define ll long long
int n,m,size[N],ch[N][2],fa[N],rev[N];
ll v[N],sum[N],fmul[N],fsum[N];
char op[5];
inline int read(){
int x=0;char ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
return x;
}
inline bool isroot(int x){return x!=ch[fa[x]][0] && x!=ch[fa[x]][1];}
inline void update(int x){
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
sum[x]=(v[x]+(sum[ch[x][0]]+sum[ch[x][1]])%mod)%mod;
}
inline void qsum(int x,int y){
v[x]=(v[x]+y)%mod;fsum[x]=(fsum[x]+y)%mod;sum[x]=(sum[x]+(ll)size[x]*y%mod)%mod;
}
inline void qmul(int x,int y){
v[x]=v[x]*y%mod;fmul[x]=fmul[x]*y%mod;fsum[x]=fsum[x]*y%mod;sum[x]=sum[x]*y%mod;
}
inline void pushdown(int x){
int l=ch[x][0],r=ch[x][1];
if(rev[x]){
rev[l]^=1;rev[r]^=1;rev[x]=0;swap(ch[x][0],ch[x][1]);
}if(fmul[x]!=1) qmul(l,fmul[x]),qmul(r,fmul[x]),fmul[x]=1;
if(fsum[x]) qsum(l,fsum[x]),qsum(r,fsum[x]),fsum[x]=0;
}
void push(int x){
if(!isroot(x)) push(fa[x]);
pushdown(x);
}
inline void rotate(int x){
int y=fa[x],z=fa[y],t=ch[y][0]==x;
if(!isroot(y)) ch[z][ch[z][1]==y]=x;
fa[y]=x;fa[x]=z;fa[ch[x][t]]=y;
ch[y][t^1]=ch[x][t];ch[x][t]=y;
update(y);update(x);
}
inline void splay(int x){
push(x);
while(!isroot(x)){
int y=fa[x];
if(isroot(y)){rotate(x);return;}
if(ch[y][0]==x^ch[fa[y]][0]==y) rotate(x);
else rotate(y);rotate(x);
}
}
inline void access(int x){
int y=0;
while(x){
splay(x);ch[x][1]=y;update(x);
y=x;x=fa[x];
}
}
inline void makeroot(int x){
access(x);splay(x);rev[x]^=1;
}
inline void link(int x,int y){
makeroot(x);fa[x]=y;
}
inline void cut(int x,int y){
makeroot(x);access(y);splay(y);
ch[y][0]=fa[x]=0;update(y);
}
inline int query(int x,int y){
makeroot(x);access(y);splay(y);return sum[y];
}
inline void dsum(int x,int y,int z){
makeroot(x);access(y);splay(y);qsum(y,z);
}
inline void dmul(int x,int y,int z){
makeroot(x);access(y);splay(y);qmul(y,z);
}
int main(){
freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) sum[i]=1,v[i]=1,fmul[i]=1;
for(int i=1;i<n;i++) link(read(),read());
for(int i=1;i<=m;i++){
scanf("%s",op);int x=read(),y=read();
if(op[0]=='+') dsum(x,y,read()%mod);
else if(op[0]=='-') cut(x,y),x=read(),y=read(),link(x,y);
else if(op[0]=='*') dmul(x,y,read()%mod);
else printf("%d\n",query(x,y));
}
return 0;
}