记录编号 391185 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2012]tree(伍一鸣) 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 8.273 s
提交时间 2017-04-05 13:45:14 内存使用 9.07 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+10,p=51061;
int n,q,w[N],next[N],head[N];
void add_edge(int f,int t){
	static int cnt=0;
	w[++cnt]=t;
	next[cnt]=head[f];
	head[f]=cnt;
}
int fa[N],son[N][2],v[N],size[N],sum[N],add[N],mul[N];
bool root[N],rev[N];
void dfs(int x){
	root[x]=1;size[x]=v[x]=sum[x]=1;
	for (int i=head[x];i;i=next[i])
		if (!fa[w[i]]) fa[w[i]]=x,dfs(w[i]);
}
//规定:先传乘法,再传加法 
#define lc son[x][0]
#define rc son[x][1]
void update(int x){
	size[x]=size[lc]+size[rc]+1;
	sum[x]=(sum[lc]+sum[rc]+v[x])%p;
}
void flip(int x){
	swap(lc,rc);rev[x]^=1;
}
void modify(int x,int a,int b){
	v[x]=((ll)v[x]*a+b)%p;
	sum[x]=((ll)sum[x]*a+(ll)size[x]*b)%p;
	add[x]=((ll)add[x]*a+b)%p;
	mul[x]=((ll)mul[x]*a)%p;
}
void pushdown(int x){
	if (!x) return;
	if (rev[x]){
		if (lc) flip(lc);
		if (rc) flip(rc);
		rev[x]=0;
	}
	if (add[x]||mul[x]!=1){
		if (lc) modify(lc,mul[x],add[x]);
		if (rc) modify(rc,mul[x],add[x]);
		add[x]=0;mul[x]=1;
	}
}
void rot(int x){
	int y=fa[x],z=fa[y];
	bool b=(x==son[y][1]);
	fa[son[y][b]=son[x][!b]]=y;
	fa[son[x][!b]=y]=x;
	fa[x]=z;
	if (y==son[z][0]) son[z][0]=x;else
	if (y==son[z][1]) son[z][1]=x;
	root[x]=root[y];root[y]=0;
	update(y);update(x);
}
void splay(int x){
	pushdown(x);
	for (;!root[x];rot(x)){
		int y=fa[x],z=fa[y];
		pushdown(z);pushdown(y);pushdown(x);
		if (root[y]) continue;
		rot((x==son[y][0])==(y==son[z][0])?y:x);
	}
}
void access(int x){
	splay(x);
	root[rc]=1;rc=0;
	update(x);
	while (fa[x]){
		int y=fa[x];
		splay(y);
		root[son[y][1]]=1;
		root[son[y][1]=x]=0;
		update(y);
		splay(x);
	}
}
void makeroot(int x){
	access(x);
	flip(x);
}
int main()
{
	freopen("nt2012_wym_tree.in","r",stdin);
	freopen("nt2012_wym_tree.out","w",stdout);
	scanf("%d%d",&n,&q);
	for (int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add_edge(x,y);
		add_edge(y,x);
	}
	fa[1]=1;dfs(1);fa[1]=0;
	int u,v,u1,v1,c;
	while (q--){
		char ch=0;
		while (ch!='+'&&ch!='-'&&ch!='*'&&ch!='/') ch=getchar();
		scanf("%d%d",&u,&v);
		makeroot(u);
		access(v);
		if (ch=='+') scanf("%d",&c),modify(v,1,c);
		if (ch=='-'){
			scanf("%d%d",&u1,&v1);
			fa[u]=son[v][0]=0;
			root[u]=1;
			update(v);
			makeroot(u1);
			fa[u1]=v1;
		}
		if (ch=='*') scanf("%d",&c),modify(v,c,0);
		if (ch=='/') printf("%d\n",sum[v]);
	}
	return 0;
}