HDU - 6394

题目链接:HDU - 6394


每个点和向上跳能到的点连边构成一棵树,然后建立一个跳出去的虚拟节点。

那么能跳到的点就是虚拟节点和当前点 split 一条链之后的size-1.


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10;
struct LCT{
	#define ls(x) t[x].ch[0]
	#define rs(x) t[x].ch[1]
	int cnt,st[N],n,q;
	struct node{int ch[2],fa,re,sz;}t[N];
	inline void push_up(int p){t[p].sz=t[ls(p)].sz+t[rs(p)].sz+1;}
	inline void push_re(int p){swap(ls(p),rs(p)); t[p].re^=1;}
	inline void push_down(int p){
		if(!t[p].re)	return;
		if(ls(p))	push_re(ls(p));	if(rs(p))	push_re(rs(p)); t[p].re^=1;
	}
	inline bool isroot(int x){return ls(t[x].fa)!=x&&rs(t[x].fa)!=x;}
	inline void rotate(int x){
		int y=t[x].fa,z=t[y].fa,k=rs(y)==x,w=t[x].ch[!k];
		if(!isroot(y))	t[z].ch[rs(z)==y]=x; t[x].ch[!k]=y; t[y].ch[k]=w;
		if(w)	t[w].fa=y; t[y].fa=x; t[x].fa=z;	push_up(y);
	}
	inline void splay(int x){
		cnt=1;	st[cnt]=x; int y=x;
		while(!isroot(y))	st[++cnt]=y=t[y].fa;
		while(cnt)	push_down(st[cnt--]);
		while(!isroot(x)){
			int y=t[x].fa,z=t[y].fa;
			if(!isroot(y))	rotate((ls(y)==x)^(ls(z)==y)?x:y); rotate(x);
		}push_up(x);
	}
	inline void access(int x){
		for(int y=0;x;x=t[y=x].fa) splay(x),rs(x)=y,push_up(x); 
	}
	inline void makeroot(int x){
		access(x); splay(x); push_re(x);
	}
	inline int find(int x){
		access(x); splay(x); while(ls(x)) push_down(x),x=ls(x); 
		splay(x);	return x;
	}
	inline void split(int x,int y){
		makeroot(x); access(y); splay(y);
	}
	inline void link(int x,int y){
		makeroot(x);	t[x].fa=y;
	}
	inline void cut(int x,int y){
		makeroot(x); 
		if(find(y)==x&&t[y].fa==x&&!ls(y)) t[y].fa=rs(x)=0,push_up(x);
	}
}lct;
int n,m,k[N],f[N][20],dep[N];
vector<int> g[N];
void dfs(int x,int fa){
	dep[x]=dep[fa]+1; f[x][0]=fa;
	for(int i=1;i<=17;i++) f[x][i]=f[f[x][i-1]][i-1];
	for(int to:g[x]) dfs(to,x);
}
inline int lca(int x,int y){
	if(dep[x]<dep[y])	swap(x,y);
	for(int i=17;i>=0;i--)	if(dep[f[x][i]]>=dep[y]) x=f[x][i];
	if(x==y)	return x;
	for(int i=17;i>=0;i--)	if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}
inline int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
inline int get(int x,int y){
	if(dep[x]-dep[1]<y)	return n+1;
	for(int i=17;i>=0;i--)	if(dep[x]-dep[f[x][i]]<=y) y-=(dep[x]-dep[f[x][i]]),x=f[x][i];
	return x;
}
void solve(){
	cin>>n;	memset(f,0,sizeof f); memset(lct.t,0,sizeof lct.t);
	for(int i=1;i<=n;i++)	g[i].clear();
	for(int i=2,x;i<=n;i++)	scanf("%d",&x),g[x].push_back(i);
	for(int i=1;i<=n;i++)	scanf("%d",&k[i]);
	dfs(1,1);
	for(int i=1;i<=n;i++)	lct.link(i,get(i,k[i]));
	cin>>m;
	for(int i=1,op,x,y;i<=m;i++){
		scanf("%d %d",&op,&x);
		if(op==1)	lct.split(x,n+1),printf("%d\n",lct.t[n+1].sz-1);
		else	scanf("%d",&y),lct.cut(x,get(x,k[x])),k[x]=y,lct.link(x,get(x,k[x]));
	}
}
signed main(){
	int T; cin>>T; while(T--) solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/107702922
hdu