SPOJ 2939 QTREE5 LCT

维护信息的方式十分巧妙~

维护每一棵 splay 中深度最浅,深度最深的点距离最近的白点.   

这样非常方便维护,进行区间合并,进行子树维护 

很多时候在维护东西的时候最大/最小/深度最小/深度最大会相对容易维护,所以如果用树剖/LCT维护信息时发现很难维护的话可以采用这种套路.

因为动态树是可以维护子树信息的,也可以 ,所以如果维护深度最深的信息的话只需 就可以做到.

code:

#include <bits/stdc++.h>  
#define N 100006 
#define inf 1000000 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;     
int n,edges; 
int hd[N],to[N<<1],nex[N<<1],col[N];    
void add(int u,int v) 
{
	nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
} 
struct Link_Cut_Tree
{ 
	#define lson p[x].ch[0] 
	#define rson p[x].ch[1]        
	struct Node 
	{
		int ch[2],f,size,lmn,rmn;    
		multiset<int>s;    
		int get() { return s.empty()?inf:*s.begin(); }
	}p[N];        
	int get(int x) { return p[p[x].f].ch[1]==x; } 
	int isrt(int x) { return !(p[p[x].f].ch[0]==x||p[p[x].f].ch[1]==x); } 
	void pushup(int x) 
	{
		p[x].size=p[lson].size+p[rson].size+1;   
		p[x].lmn=min(p[lson].lmn, p[lson].size+min(col[x]?0:inf, min(p[x].get(), p[rson].lmn+1)));
		p[x].rmn=min(p[rson].rmn, p[rson].size+min(col[x]?0:inf, min(p[x].get(), p[lson].rmn+1)));         	
	}
	void rotate(int x) 
	{
		int old=p[x].f,fold=p[old].f,which=get(x);  
		if(!isrt(old)) p[fold].ch[p[fold].ch[1]==old]=x;    
		p[old].ch[which]=p[x].ch[which^1],p[p[old].ch[which]].f=old; 
		p[x].ch[which^1]=old,p[old].f=x,p[x].f=fold; 
		pushup(old),pushup(x); 
	}  
	void splay(int x) 
	{
		int u=x,v=0,fa;
		for(;!isrt(u);u=p[u].f);   
		for(u=p[u].f;(fa=p[x].f)!=u;rotate(x)) 
		    if(p[fa].f!=u) 
			    rotate(get(fa)==get(x)?fa:x); 
	}
	void Access(int x) 
	{
		for(int y=0;x;y=x,x=p[x].f) 
		{
		    splay(x); 
			if(rson) 
			{
				p[x].s.insert(p[rson].lmn+1);      
			}
			if(y) 
			{
				p[x].s.erase(p[x].s.find(p[y].lmn+1));    
			}
			rson=y; 
			pushup(x); 
		}
	}    
	#undef lson 
	#undef rson 
}lct;  
void dfs(int u,int ff) 
{
	lct.p[u].f=ff;     
	for(int i=hd[u];i;i=nex[i]) 
	{
		int v=to[i]; 
		if(v==ff) continue;               
		dfs(v,u);        
		lct.p[u].s.insert(inf+1); 
	}   
	lct.pushup(u); 
}
int main() 
{ 
	// setIO("input"); 
	int i,j; 
	scanf("%d",&n); 
	for(i=1;i<n;++i) 
	{
		int u,v; 
		scanf("%d%d",&u,&v); 
		add(u,v); 
		add(v,u); 
	} 
	lct.p[0].lmn=lct.p[0].rmn=inf;   
	dfs(1,0);               
	int m; 
	scanf("%d",&m); 
	for(i=1;i<=m;++i) 
	{
		int op,u; 
		scanf("%d%d",&op,&u);    
		if(op==0) 
		{
			lct.Access(u); 
			lct.splay(u);    
			col[u]^=1;    
			lct.pushup(u);     
		}
		else 
		{
			lct.Access(u);  
			lct.splay(u);    
			printf("%d\n",lct.p[u].rmn>n?-1:lct.p[u].rmn);    
		}  
	}
	return 0;
}

  

posted @ 2019-10-14 16:49  EM-LGH  阅读(138)  评论(0编辑  收藏  举报