BZOJ 4817: [Sdoi2017]树点涂色 LCT+Access的性质+DFS序+线段树

Code:

#include<bits/stdc++.h> 
#define maxn 200003 
#define inf -1000000 
using namespace std;
void setIO(string s)
{
	string in=s+".in",out=s+".out"; 
	freopen(in.c_str(),"r",stdin); 
	freopen(out.c_str(),"w",stdout); 
}
int tim,edges,n,Q,_curcol; 
int dfn[maxn],ln[maxn],fa[maxn],hd[maxn],to[maxn<<1],nex[maxn<<1];
int st[maxn],ed[maxn],top[maxn],hson[maxn],siz[maxn],dep[maxn]; 
void addedge(int u,int v)
{
	nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
}
namespace tr
{
	int maxv[maxn<<2],lazy[maxn<<2];           
	void mark(int x,int k)
	{         
		lazy[x]+=k, maxv[x]+=k; 
	}
	void pushdown(int l,int r,int x)      
	{      
		if(!lazy[x]) return; 
		int mid=(l+r)>>1; 
		if(mid>=l) mark(x<<1,lazy[x]); 
		if(r>mid) mark((x<<1)|1,lazy[x]); 
		lazy[x]=0; 
	}
	void update(int l,int r,int x,int L,int R,int k)
	{
		if(l>=L&&r<=R)
		{
			mark(x,k);                      
			return; 
		}
		pushdown(l,r,x); 
		int mid=(l+r)>>1; 
		if(L<=mid) update(l,mid,x<<1,L,R,k); 
		if(R>mid) update(mid+1,r,(x<<1)|1,L,R,k); 
		maxv[x]=max(maxv[x<<1],maxv[(x<<1)|1]); 
	}
	int query(int l,int r,int x,int L,int R)
	{
		if(l>=L&&r<=R) return maxv[x]; 
		pushdown(l,r,x); 
		int mid=(l+r)>>1, tmp=inf; 
		if(L<=mid) tmp=max(tmp,query(l,mid,x<<1,L,R)); 
		if(R>mid) tmp=max(tmp,query(mid+1,r,(x<<1)|1,L,R)); 
		return tmp; 
	}       
	int po(int l,int r,int x,int k)
	{
		if(l==r) return maxv[x]; 
		int mid=(l+r)>>1; 
		pushdown(l,r,x); 
		if(k<=mid) return po(l,mid,x<<1,k); 
		else return po(mid+1,r,(x<<1)|1,k); 
	}            
}; 
namespace tree
{
	#define lson ch[x][0] 
	#define rson ch[x][1]
	#define get(x) (ch[f[x]][1]==x) 
	#define isrt(x) (!(ch[f[x]][0]==x||ch[f[x]][1]==x))  
	int ch[maxn][2],f[maxn],col[maxn],sta[maxn]; 
	void pushdown(int x)
	{
		if(!x) return; 
		if(col[x])
		{
			if(lson) col[lson]=col[x]; 
			if(rson) col[rson]=col[x]; 
		}
	} 
	int findrt(int x)
	{
		while(lson)x=lson; 
		return x; 
	}
	void rotate(int x)
	{
		int old=f[x],fold=f[old],which=get(x); 
		if(!isrt(old)) ch[fold][ch[fold][1]==old]=x; 
		ch[old][which]=ch[x][which^1], f[ch[old][which]]=old; 
		ch[x][which^1]=old,f[old]=x,f[x]=fold; 
	}
	void splay(int x)
	{
		int u=x,v=0,fa; 
		sta[++v]=u; 
		while(!isrt(u)) sta[++v]=f[u],u=f[u]; 
		while(v) pushdown(sta[v--]); 
		for(u=f[u];(fa=f[x])!=u;rotate(x))
			if(f[fa]!=u) 
				rotate(get(fa)==get(x)?fa:x); 
	}
	void Access(int x,int co)
	{
		int t=0,son; 
		while(x)
		{
			splay(x); 
			if(t) son=findrt(t), tr::update(1,n,1,st[son],ed[son],-1);    
			if(rson) son=findrt(rson),tr::update(1,n,1,st[son],ed[son],1);      
			col[x]=co,rson=t,t=x,x=f[x];               
		}
	}
};  
void dfs1(int u,int ff)
{ 
	fa[u]=ff;
	siz[u]=1;
	dep[u]=dep[ff]+1; 
	ln[++tim]=u;
	dfn[u]=st[u]=tim;  
	tr::update(1,n,1,dfn[u],dfn[u],dep[u]);      
	tree::f[u]=ff;                           
	for(int i=hd[u];i;i=nex[i])
	{
		int v=to[i];
		if(v==ff) continue; 
		dfs1(v,u); 
		siz[u]+=siz[v]; 
		if(siz[v]>siz[hson[u]]) hson[u]=v; 
	} 
	ed[u]=tim;         
}
void dfs2(int u,int tp)
{
	top[u]=tp;           
	if(hson[u]) dfs2(hson[u],tp); 
	for(int i=hd[u];i;i=nex[i])
	{
		int v=to[i];
		if(v==hson[u]||v==fa[u]) continue; 
		dfs2(v,v); 
	}       
}
int LCA(int x,int y)
{
	while(top[x]^top[y]) dep[top[x]] < dep[top[y]] ? y = fa[top[y]] : x = fa[top[x]]; 
	return dep[x] < dep[y] ? x : y; 
}
int main()
{
	// setIO("input");
	scanf("%d%d",&n,&Q);   
	tr::maxv[0]=inf;         
	for(int i=1,u,v;i<n;++i) 
	{
		scanf("%d%d",&u,&v); 
		addedge(u,v); 
		addedge(v,u); 
	}
	dfs1(1,0); 
	dfs2(1,1);  
	int opt,x,y,lca,ou=0; 
	while(Q--)
	{
		scanf("%d",&opt); 
		switch(opt)
		{
			case 1 : 
			{
				scanf("%d",&x);  
				tree::Access(x,++_curcol); 
				break; 
			}
			case 2 : 
			{
				scanf("%d%d",&x,&y); 
				lca=LCA(x,y); 
				ou=0;  
				ou+=tr::po(1,n,1,dfn[x]);                         
				ou+=tr::po(1,n,1,dfn[y]);         
				ou-=tr::po(1,n,1,dfn[lca])<<1;            
				ou+=1; 
				printf("%d\n",ou); 
				break; 
			}
			case 3 :
			{
				scanf("%d",&x);       
				printf("%d\n",tr::query(1,n,1,st[x],ed[x])); 
				break; 
			}
		}
	} 
	return 0; 
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/11027343.html