记录编号 217656 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2012]tree(伍一鸣) 最终得分 100
用户昵称 Gravatarstdafx.h 是否通过 通过
代码语言 C++ 运行时间 8.579 s
提交时间 2016-01-05 17:37:22 内存使用 6.39 MiB
显示代码纯文本
#define MAXN 100010UL
#define MAXC 5UL

#define uint unsigned int

#define Mod 51061UL

#include <stdio.h>
#include <string.h>

#define L(x) ch[x][0]
#define R(x) ch[x][1]

struct Edge{int v,nx;};
Edge edge[MAXN<<1];
uint n,q,ec,val[MAXN],sum[MAXN],fa[MAXN],mark[MAXN],add[MAXN],mul[MAXN],sta[MAXN],ch[MAXN][2],tag[MAXN],size[MAXN],headlist[MAXN];
char op[MAXC];

/*---------------------------------------------
 -  mark == 0 is nuuint .                       +
 -  mark == 1 is add .                        +
 -  mark == 2 is mul .                        +
 -  mark == 3 is firstly mul & secondly add . +
---------------------------------------------*/

inline uint in(){
	uint x=0,c=getchar();
	while(c<'0'||c>'9') c=getchar();
	for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return x;
}

inline bool IsRoot(uint x){
	return (fa[x]==0)||(L(fa[x])!=x&&R(fa[x])!=x);
}

inline void Add_Edge(uint u,uint v){
	edge[++ec].v=v;
	edge[ec].nx=headlist[u];
	headlist[u]=ec;
	return;
}

inline void dfs(uint p,uint k){
	fa[p]=k;
	val[p]=sum[p]=size[p]=1;
	for(uint i=headlist[p];i;i=edge[i].nx){
		if(edge[i].v==k) continue;
		dfs(edge[i].v,p);
	}
	return;
}

inline void Update(uint x){
	sum[x]=val[x];
	size[x]=1;
	if(L(x)) size[x]+=size[L(x)],sum[x]+=sum[L(x)];
	if(R(x)) size[x]+=size[R(x)],sum[x]+=sum[R(x)];
	sum[x]%=Mod;
	size[x]%=Mod;
	return;
}

inline void GiveMark(uint mark_type,uint x,uint adding,uint muling){
	adding%=Mod;
	muling%=Mod;
	if(mark_type==1){
		add[x]+=adding;
		val[x]+=adding;
		sum[x]+=size[x]*adding;
		if(!mark[x]) mark[x]=1;
		else if(mark[x]==2) mark[x]=3;
	}
	else if(mark_type==2){
		val[x]*=muling;
		sum[x]*=muling;
		if(!mark[x]) mark[x]=2,mul[x]=muling;
		else if(mark[x]==1) mark[x]=3,mul[x]=muling,add[x]*=muling;
		else if(mark[x]==2) mul[x]*=muling;
		else if(mark[x]==3) mul[x]*=muling,add[x]*=muling;
	}
	else if(mark_type==3){
		val[x]*=muling;val[x]+=adding;
		sum[x]*=muling;sum[x]+=size[x]*adding;
		if(!mark[x]) mark[x]=3,mul[x]=muling,add[x]=adding;
		else if(mark[x]==1) mark[x]=3,mul[x]=muling,add[x]*=muling,add[x]%=Mod,add[x]+=adding;
		else if(mark[x]==2) mark[x]=3,mul[x]*=muling,add[x]+=adding;
		else if(mark[x]==3) mul[x]*=muling,add[x]*=muling,add[x]%=Mod,add[x]+=adding;
	}
	mul[x]%=Mod;add[x]%=Mod;sum[x]%=Mod;val[x]%=Mod;
	return;
}

inline void Swap(uint &x,uint &y){
	if(x!=y) x^=y,y^=x,x^=y;
	return;
}

inline void PushDown(uint x){
	if(tag[x]!=0){Swap(L(x),R(x));tag[L(x)]^=1;tag[R(x)]^=1;tag[x]=0;}
	if(mark[x]!=0){
		if(L(x)) GiveMark(mark[x],L(x),add[x],mul[x]);
		if(R(x)) GiveMark(mark[x],R(x),add[x],mul[x]);
		mark[x]=0;add[x]=0;mul[x]=0;
	}
	return;
}

inline void Rotate(uint x,uint d){
	uint y=ch[x][d^1];
	ch[x][d^1]=ch[y][d];
	fa[ch[x][d^1]]=x;ch[y][d]=x;
	if(x==L(fa[x])) L(fa[x])=y;
	else if(x==R(fa[x])) R(fa[x])=y;
	fa[y]=fa[x];fa[x]=y;
	Update(x);return;
}

inline void Splay(uint p){
	sta[++sta[0]]=p;
	for(uint i=p;!IsRoot(i);i=fa[i]) sta[++sta[0]]=fa[i];
	while(sta[0]) PushDown(sta[sta[0]--]);
	uint x,y;
	while(!IsRoot(p)){
		x=fa[p];y=fa[x];
		if(IsRoot(x)) Rotate(x,L(x)==p);
		else{
			if((L(x)==p)==(L(y)==x)){Rotate(y,L(y)==x);Rotate(x,L(x)==p);}
			else{Rotate(x,L(x)==p);Rotate(y,L(y)==p);}
		}
	}
	Update(p);
	return;
}

inline void Access(uint x){
	uint t=0;
	while(x){
		Splay(x);PushDown(x);
		R(x)=t;Update(x);
		t=x;x=fa[x];
	}
	return;
}

inline void MakeRoot(uint x){
	Access(x);
	Splay(x);
	tag[x]^=1;
	return;
}

inline void Link(uint x,uint y){
	MakeRoot(x);fa[x]=y;
	return;
}

inline void Cut(uint x,uint y){
	MakeRoot(x);
	Access(y);Splay(y);
	PushDown(y);
	if(L(y)==x) L(y)=fa[x]=0;
	Update(y);
	return;
}

inline void Add(uint x,uint y,uint c){
	Access(y);
	uint t=0;
	while(x){
		Splay(x);PushDown(x);
		if(!fa[x]){
			val[x]+=c;
			val[x]%=Mod;
			GiveMark(1,R(x),c,0);
			GiveMark(1,t,c,0);
			Update(x);
			return;
		}
		R(x)=t;Update(x);
		t=x;x=fa[x];
	}
	return;
}

inline void Mul(uint x,uint y,uint c){
	Access(y);
	uint t=0;
	while(x){
		Splay(x);PushDown(x);
		if(!fa[x]){
			val[x]*=c;
			val[x]%=Mod;
			GiveMark(2,R(x),0,c);
			GiveMark(2,t,0,c);
			Update(x);
			return;
		}
		R(x)=t;Update(x);
		t=x;x=fa[x];
	}
	return;
}

inline uint GetAns(uint x,uint y){
	Access(y);
	uint t=0;
	while(x){
		Splay(x);PushDown(x);
		if(!fa[x]) return (val[x]+sum[R(x)]+sum[t])%Mod;
		R(x)=t;Update(x);
		t=x;x=fa[x];
	}
	return 0;
}

int main(){
	freopen("nt2012_wym_tree.in","r",stdin);
	freopen("nt2012_wym_tree.out","w",stdout);
	n=in();q=in();
	for(uint i=1,a,b;i<n;i++){
		a=in();b=in();
		Add_Edge(a,b);
		Add_Edge(b,a);
	}
	dfs(1,0);
	for(uint i=0,a,b,c,d;i<q;i++){
		scanf("%s",op);
		if(op[0]=='+') a=in(),b=in(),c=in(),Add(a,b,c);
		else if(op[0]=='-') a=in(),b=in(),c=in(),d=in(),Cut(a,b),Link(c,d);
		else if(op[0]=='*') a=in(),b=in(),c=in(),Mul(a,b,c);
		else a=in(),b=in(),printf("%u\n",GetAns(a,b));
	}
	return 0;
}