裸的lct…注意*和+标记之间的影响以及下放顺序即可
省选前练习模板系列…
讲道理开unsigned int就可以了,常数会小一些,不过我的能过就无所谓了…
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
//by:MirrorGray
using namespace std;
const int N=211111,mod=51061;
struct LCT{int l,r,fa,d,sum,rev,add,mul,size;}sp[N];
int MOD(int x){
while(x>=mod)x-=mod;
while(x<0)x+=mod;
return x;
}
void rev(int tr){
if(!tr)return ;
swap(sp[tr].l,sp[tr].r);
sp[tr].rev^=1;
}
void add(int tr,int d){
if(!tr||!d)return ;
sp[tr].d=MOD(sp[tr].d+d);
sp[tr].sum=MOD(sp[tr].sum+(ll)sp[tr].size*d%mod);
sp[tr].add=MOD(sp[tr].add+d);
}
void mul(int tr,int d){
if(!tr||d==1)return ;
sp[tr].d=(ll)sp[tr].d*d%mod;
sp[tr].sum=(ll)sp[tr].sum*d%mod;
sp[tr].add=(ll)sp[tr].add*d%mod;
sp[tr].mul=(ll)sp[tr].mul*d%mod;
}
void down(int tr){
int l=sp[tr].l,r=sp[tr].r;
if(sp[tr].rev)rev(l),rev(r),sp[tr].rev=0;
if(sp[tr].mul!=1){
mul(l,sp[tr].mul);
mul(r,sp[tr].mul);
sp[tr].mul=1;
}
if(sp[tr].add){
add(l,sp[tr].add);
add(r,sp[tr].add);
sp[tr].add=0;
}
}
void up(int tr){
int l=sp[tr].l,r=sp[tr].r;
sp[tr].size=1;sp[tr].sum=sp[tr].d;
if(l){
sp[tr].size+=sp[l].size;
sp[tr].sum=MOD(sp[tr].sum+sp[l].sum);
}
if(r){
sp[tr].size+=sp[r].size;
sp[tr].sum=MOD(sp[tr].sum+sp[r].sum);
}
}
bool is(int tr){
return sp[sp[tr].fa].l!=tr&&sp[sp[tr].fa].r!=tr;
}
void zig(int tr){
int y=sp[tr].fa;
sp[y].l=sp[tr].r;
if(sp[tr].r)sp[sp[tr].r].fa=y;
sp[tr].fa=sp[y].fa;
if(sp[y].fa){
if(sp[sp[y].fa].l==y)sp[sp[y].fa].l=tr;
else if(sp[sp[y].fa].r==y)sp[sp[y].fa].r=tr;
}
sp[tr].r=y;sp[y].fa=tr;
up(y);
}
void zag(int tr){
int y=sp[tr].fa;
sp[y].r=sp[tr].l;
if(sp[tr].l)sp[sp[tr].l].fa=y;
sp[tr].fa=sp[y].fa;
if(sp[y].fa){
if(sp[sp[y].fa].l==y)sp[sp[y].fa].l=tr;
else if(sp[sp[y].fa].r==y)sp[sp[y].fa].r=tr;
}
sp[tr].l=y;sp[y].fa=tr;
up(y);
}
int list[N];
void splay(int tr){
int p=tr,t=0;
while(!is(p))list[++t]=p,p=sp[p].fa;
if(p)down(p);
for(int i=t;i;i--)down(list[i]);
while(!is(tr)){
int y=sp[tr].fa;
if(is(y)){
if(sp[y].l==tr)zig(tr);
else zag(tr);
}
else{
if(sp[sp[y].fa].l==y){
if(sp[y].l==tr)zig(y),zig(tr);
else zag(tr),zig(tr);
}
else{
if(sp[y].l==tr)zig(tr),zag(tr);
else zag(y),zag(tr);
}
}
}
up(tr);
}
void access(int tr){
int y=0;
while(tr){
splay(tr);sp[tr].r=y;
up(tr);
y=tr;tr=sp[tr].fa;
}
}
void movert(int tr){
access(tr);splay(tr);rev(tr);
}
void link(int a,int b){
movert(b);sp[b].fa=a;
}
void cut(int a,int b){
movert(a);access(b),splay(b);
if(sp[b].l!=a)while(true)puts("fuck");
sp[b].l=0;sp[a].fa=0;
up(b);
}
int main(){
int n,q;scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)sp[i].d=sp[i].mul=1,up(i);
for(int i=1;i<n;i++){
int a,b;scanf("%d%d",&a,&b);
link(a,b);
}
while(q--){
char s[2];scanf("%s",s);
if(s[0]=='+'){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
movert(a);access(b);splay(b);add(b,c);
}
if(s[0]=='-'){
int a,b,c,d;scanf("%d%d%d%d",&a,&b,&c,&d);
cut(a,b);link(c,d);
}
if(s[0]=='*'){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
movert(a);access(b);splay(b);mul(b,c);
}
if(s[0]=='/'){
int a,b;scanf("%d%d",&a,&b);
movert(a);access(b);splay(b);
printf("%d\n",sp[b].sum);
}
}
return 0;
}