记录编号 217477 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [HZOI 2015] 可持久化动态树(题目有误) 最终得分 100
用户昵称 Gravatarstdafx.h 是否通过 通过
代码语言 C++ 运行时间 2.441 s
提交时间 2016-01-03 18:58:41 内存使用 291.64 MiB
显示代码纯文本
#define MAXN 100010UL
#define MAXT 20000010UL
#define MAXC 10UL

#define Ander 16383L

#include <stdio.h>

struct Edge{int v,nx;};
Edge edge[MAXN<<1];

int n,ec,q,dfs_clock,cnt,current,root_cnt,posl,posr,update_val,op_root[MAXN],depth[MAXN],headlist[MAXN],siz[MAXN],top[MAXN],son[MAXN],fa[MAXN],dfn[MAXN],ots[MAXN],root[MAXT],ch[MAXT][2],mark[MAXT],tree[MAXT];
char op[MAXC];

inline int in(){
	int 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 void Add_Edge(int u,int v){
	edge[++ec].v=v;
	edge[ec].nx=headlist[u];
	headlist[u]=ec;
	return;
}

inline void ReadIn(){
	n=in();q=in();
	for(int i=1,a,b;i<n;i++){
		a=in();b=in();
		Add_Edge(a,b);
		Add_Edge(b,a);
	}
	return;
}

inline void dfs1(int p){
	siz[p]|=1;
	for(int i=headlist[p];i;i=edge[i].nx){
		if(fa[p]==edge[i].v) continue;
		fa[edge[i].v]=p;
		depth[edge[i].v]=depth[p]+1;
		dfs1(edge[i].v);
		siz[p]+=siz[edge[i].v];
		if(siz[edge[i].v]>siz[son[p]]) son[p]=edge[i].v;
	}
	return;
}

inline void dfs2(int p,int tp){
	top[p]=tp;
	dfn[p]=++dfs_clock;
	if(son[p]) dfs2(son[p],tp);
	for(int i=headlist[p];i;i=edge[i].nx){
		if(edge[i].v==fa[p]||edge[i].v==son[p]) continue;
		dfs2(edge[i].v,edge[i].v);
	}
	ots[p]=dfs_clock;
	return;
}

inline void Build(int l,int r,int &id){
	id=++cnt;
	if(l==r) return;
	int mid=(l+r)>>1;
	Build(l,mid,ch[id][0]);
	Build(mid+1,r,ch[id][1]);
	return;
}

inline void PreWork(){
	dfs1(1);
	dfs2(1,1);
	Build(1,n,root[0]);
	return;
}

inline void Clear(int l,int r,int rt){
	if(mark[rt]==0||l==r) return;
	int mid=(l+r)>>1;
	tree[++cnt]=tree[ch[rt][0]];
	mark[cnt]=mark[ch[rt][0]];
	ch[cnt][0]=ch[ch[rt][0]][0];
	ch[cnt][1]=ch[ch[rt][0]][1];
	ch[rt][0]=cnt;
	tree[++cnt]=tree[ch[rt][1]];
	mark[cnt]=mark[ch[rt][1]];
	ch[cnt][0]=ch[ch[rt][1]][0];
	ch[cnt][1]=ch[ch[rt][1]][1];
	ch[rt][1]=cnt;
	if(mark[rt]==-1){
		tree[ch[rt][0]]=0;
		tree[ch[rt][1]]=0;
		mark[ch[rt][0]]=-1;
		mark[ch[rt][1]]=-1;
	}
	else{
		tree[ch[rt][0]]+=(mid-l+1LL)*mark[rt];
		tree[ch[rt][1]]+=(r-mid)*mark[rt];
		tree[ch[rt][0]]&=Ander;
		tree[ch[rt][1]]&=Ander;
		if(mark[ch[rt][0]]==-1) mark[ch[rt][0]]=mark[rt];
		else if(mark[rt]!=-1) mark[ch[rt][0]]+=mark[rt];
		else mark[ch[rt][0]]=-1;
		if(mark[ch[rt][1]]==-1) mark[ch[rt][1]]=mark[rt];
		else if(mark[rt]!=-1) mark[ch[rt][1]]+=mark[rt];
		else mark[ch[rt][1]]=-1;
	}
	mark[rt]=0;
	return;
}

inline void Update(int l,int r,int p,int &now){
	now=++cnt;
	Clear(l,r,p);
	if(posl<=l&&posr>=r){
		ch[now][0]=ch[p][0];
		ch[now][1]=ch[p][1];
		mark[now]=(update_val+mark[p])&Ander;
		tree[now]=tree[p]+(r-l+1LL)*update_val;
		return;
	}
	int mid=(l+r)>>1;
	if(posl<=mid) Update(l,mid,ch[p][0],ch[now][0]);
	else ch[now][0]=ch[p][0];
	if(posr>mid) Update(mid+1,r,ch[p][1],ch[now][1]);
	else ch[now][1]=ch[p][1];
	tree[now]=tree[ch[now][0]]+tree[ch[now][1]];
	tree[now]&=Ander;
	return;
}

inline void Div(int l,int r,int p,int &now){
	now=++cnt;
	Clear(l,r,p);
	if(posl<=l&&posr>=r){
		ch[now][0]=ch[p][0];
		ch[now][1]=ch[p][1];
		mark[now]=-1;
		tree[now]=0;
		return;
	}
	int mid=(l+r)>>1;
	if(posl<=mid) Div(l,mid,ch[p][0],ch[now][0]);
	else ch[now][0]=ch[p][0];
	if(posr>mid) Div(mid+1,r,ch[p][1],ch[now][1]);
	else ch[now][1]=ch[p][1];
	tree[now]=tree[ch[now][0]]+tree[ch[now][1]];
	tree[now]&=Ander;
	return;
}

inline int Query(int l,int r,int rt){
    Clear(l,r,rt);
	if(posl<=l&&posr>=r) return tree[rt];
	int mid=(l+r)>>1,Ans=0;
	if(posl<=mid) Ans+=Query(l,mid,ch[rt][0]),Ans&=Ander;
	if(posr>mid) Ans+=Query(mid+1,r,ch[rt][1]),Ans&=Ander;
	return Ans;
}

inline int Q(int l,int r){
	if(l>r) return 0LL;
	posl=l,posr=r;
	return Query(1,n,root[current]);
}

inline void Sub(int l,int r){
	if(l>r) return;
	posl=l,posr=r;
	Div(1,n,root[current],root[++root_cnt]);
	current=root_cnt;
	return;
}

inline void Modify(int l,int r,int delta){
	if(l>r) return;
	posl=l,posr=r;
	update_val=delta;
	Update(1,n,root[current],root[++root_cnt]);
	current=root_cnt;
	return;
}

inline void BWork(){
	int x,delta;
	x=in();delta=in();
	Modify(dfn[x],ots[x],delta);
	return;
}

inline void CWork(){
	int x,y,delta;
	x=in();y=in();delta=in();
	if(depth[x]<depth[y]) x^=y,y^=x,x^=y;
	while(top[x]!=top[y]){
		Modify(dfn[top[x]],dfn[x],delta);
		x=fa[top[x]];
	}
	Modify(dfn[y],dfn[x],delta);
	return;
}

inline int QWork(){
	int x,y,Ans=0;
	x=in();y=in();
	if(depth[x]<depth[y]) x^=y,y^=x,x^=y;
	while(top[x]!=top[y]){
		Ans+=Q(dfn[top[x]],dfn[x]);
		Ans&=Ander;
		x=fa[top[x]];
	}
	Ans+=Q(dfn[y],dfn[x]);
	return Ans&Ander;
}

inline void EWork(){
	int x,y;
	x=in();y=in();
	if(depth[x]<depth[y]) x^=y,y^=x,x^=y;
	while(top[x]!=top[y]){
		Sub(dfn[top[x]],dfn[x]);
		x=fa[top[x]];
	}
	Sub(dfn[y],dfn[x]);
	return;
}

inline void Answer(){
	for(int i=1;i<=q;i++){
		scanf("%s",op);
		if(op[0]=='B') BWork();
		else if(op[0]=='C') CWork();
		else if(op[0]=='Q') printf("%d\n",QWork());
		else if(op[0]=='E') EWork();
		else if(op[0]=='R') current=op_root[in()];
		op_root[i]=current;
	}
	return;
}

int main(){
	freopen("great_tree.in","r",stdin);
	freopen("great_tree.out","w",stdout);
	ReadIn();
	PreWork();
	Answer();
	return 0;
}