记录编号 313952 评测结果 AAAAA
题目名称 [HZOI 2015]白黑树 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.306 s
提交时间 2016-10-02 15:10:50 内存使用 22.22 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=500010;
int fa[N],son[N][2],s[N],key[N];//key为该子树上黑点个数 
int add[N];bool root[N];//增加标记,根标记 
struct edge{int f,t;}w[N];
int n,m,q,head[N],tail[N],next[N];
int now;bool c[N];//now为当前黑点个数,c为当前颜色 
inline void add_e(int f,int num){
	if (!head[f]) head[f]=tail[f]=num;
		else tail[f]=next[tail[f]]=num;
}
void dfs(int x){//初始化 
	root[x]=1;
	for (int i=head[x];i;i=next[i])
	if (!root[w[i].t]){
		fa[w[i].t]=x;
		s[w[i].t]=root[w[i].t]=1;
		dfs(w[i].t);
	}
}
//namespace LCT{
	inline void update(int x){//动态更新 
		s[x]=s[son[x][0]]+s[son[x][1]]+1;
	}
	inline void rotate(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);
	}
	inline void pushdown(int x){//下传标记 
		if (add[x]){
			int l=son[x][0],r=son[x][1];
			add[l]+=add[x];add[r]+=add[x];
			key[l]+=add[x];key[r]+=add[x];
			add[x]=key[0]=add[0]=0;
		}
	}
	inline void splay(int x){//旋至链顶 
		pushdown(x);
		while (!root[x]){
			int y=fa[x],z=fa[y];
			pushdown(z);pushdown(y);pushdown(x);
			if (root[y]){rotate(x);return;}
			if (x==son[y][0]) rotate(y==son[z][0]?y:x);
				else rotate(y==son[z][1]?y:x);
			rotate(x);
		}
	}
	inline void access(int x){//将x到根路径设为优先路径 
		splay(x);
		root[son[x][1]]=1;
		son[x][1]=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);
		}
	}
	inline void Add(int x,int d){//将x到根路径上数目修改掉 
		access(x);
		add[x]+=d;
		key[x]+=d;
	}
	int splay(int x,int k){//将以x为根的splay的第k个元素伸展到根,并返回该元素 
		int l=son[x][0],r=son[x][1],i=s[l]+1,ans;
		pushdown(x);
		if (i==k) return x;
		if (k<i) ans=splay(l,k),rotate(son[x][0]);
			else ans=splay(r,k-i),rotate(son[x][1]);
		return ans;
	}
//}
void erfen(int x,int l,int r){//子树x上二分 
	if (l==r){printf("%d\n",splay(x,l));return;}
	int mid=(l+r)/2,next=splay(x,mid+1);
	if (key[next]>=now) erfen(next,mid+1,r);
		else erfen(next,l,mid);
}
char ch[10];int x;
int main()
{
	freopen("C_Tree.in","r",stdin);
	freopen("C_Tree.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<n;i++){
		scanf("%d%d",&w[i].f,&w[i].t);
		w[i+n].f=w[i].t;w[i+n].t=w[i].f;
		add_e(w[i].f,i);add_e(w[i].t,i+n);
	}
	dfs(1);
	while (m--){
		scanf("%s%d",ch,&x);
		if (ch[0]=='M')
			if (c[x]) c[x]=0,now--,Add(x,-1);
				else c[x]=1,now++,Add(x,1);
		else
			if (now){access(x);erfen(x,1,s[x]);}
				else puts("-1");
	}
	return 0;
}