BZOJ 4551 [Tjoi2016&Heoi2016]树

题解:动态树,维护Splay最深的被标记过的点

每个询问先Access(x);

当然用树链剖分也可以

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=100009;
const int oo=1000000000;

int n,T;

int fa[maxn],ch[maxn][2],dest[maxn],v[maxn];
inline int son(int x){
	if(ch[fa[x]][1]==x)return 1;
	else return 0;
}
inline void pushup(int x){
	dest[x]=dest[ch[x][1]];
	if(!dest[x]){
		if(v[x])dest[x]=x;
	}
	if(!dest[x])dest[x]=dest[ch[x][0]];
}
inline bool isroot(int x){
	return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
}

inline void Rotate(int x){
	int y=fa[x];
	int z=fa[y];
	int b=son(x),c=son(y);
	int a=ch[x][b^1];
	if(!isroot(y))ch[z][c]=x;
	fa[x]=z;
	if(a)fa[a]=y;
	ch[y][b]=a;
	fa[y]=x;ch[x][b^1]=y;
	pushup(y);pushup(x);
}
void Splay(int x){
	while(!isroot(x)){
		int y=fa[x];
		if(isroot(y)){
			Rotate(x);
		}else{
			if(son(x)==son(y)){
				Rotate(y);Rotate(x);
			}else{
				Rotate(x);Rotate(x);
			}
		}
	}
}

void Access(int x){
	for(int t=0;x;t=x,x=fa[x]){
		Splay(x);ch[x][1]=t;pushup(x);
	}
}


int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
	 nex[++cntedge]=head[x];
	 to[cntedge]=y;
	 head[x]=cntedge;
}

queue<int>q;
int father[maxn];
void Bfs(){
	q.push(1);
	while(!q.empty()){
		int x=q.front();q.pop();
		for(int i=head[x];i;i=nex[i]){
			if(to[i]==father[x])continue;
			father[to[i]]=x;
			fa[to[i]]=x;
			q.push(to[i]);
		}
	}
}

int main(){
	scanf("%d%d",&n,&T);
	for(int i=1;i<=n-1;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		Addedge(x,y);
		Addedge(y,x);
	}
	
	v[1]=1;dest[1]=1;
	Bfs();
	while(T--){
		char opty[10];
		scanf("%s",opty);
		int x;
		scanf("%d",&x);
		if(opty[0]=='C'){
			Splay(x);v[x]=1;pushup(x);
		}else{
			Access(x);Splay(x);printf("%d\n",dest[x]);
		}
	}
	return 0;
}

  

posted @ 2018-02-19 20:05  ws_zzy  阅读(135)  评论(0编辑  收藏  举报