vijos lxhgww的奇思妙想

vijos lxhgww的奇思妙想

本题我们可以通过倍增的预处理\(O(nlogn)\),然后对本题进行长链剖分。 对于要求k级祖先,我们先用预处理好的倍增数组走到x的\(highbit(k)\)祖先上面去(10的highbit就是8,剩余的k就是2了),x变成这个highbit的祖先。然后我们讨论x和\(top[x]\)之间的距离,如果大于等于剩余的k,那么我们就求\(top[x]\)下面距离为\(dep[x]-dep[top[x]]-k\)的长链的节点编号。如果小于等于剩下的k,我们就求\(top[x]\)上面的距离为\(k-dep[x]+dep[top[x]]\)的节点的编号。这些上面的节点和下面的节点我们都可以提前预处理,因为我们只要记录每个长链的顶端节点的上下节点就可以,时间复杂度是\(o(n)\)的。
本题时间复杂度最高的地方在于倍增求\(2^k\)的祖先,每次在线处理k级祖先是\(o(1)\)的。 总的时间复杂度也是\(O(nlogn\))。

#pragma comment(linker, "/STACK:1024000000,1024000000") 
#include<bits/stdc++.h>
using namespace std;  
int const N=500000+10; 
struct edge{
	int to,nt;  
}e[N<<1];  
int f[N][20],n,cnt,h[N],top[N],son[N],dep[N],md[N],len[N],m,hb[N<<1];  
vector<int> U[N],D[N];  
void add(int a,int b){
	e[++cnt].to=b;  
	e[cnt].nt=h[a];  
	h[a]=cnt++;  
}
void dfs(int x,int fa){
	dep[x]=md[x]=dep[fa]+1; f[x][0]=fa;  
	for(int i=1;i<=18;i++) f[x][i]=f[f[x][i-1]][i-1];  
	for(int i=h[x];i;i=e[i].nt){
		int v=e[i].to;  
		if(v==fa) continue;  
		dfs(v,x);  
		if(md[x]<md[v]) 
			son[x]=v,md[x]=md[v];
	}
}	
void dfs2(int x,int fa,int tp){
	top[x]=tp; len[x]=md[x]-dep[top[x]]+1;  
	for(int i=h[x];i;i=e[i].nt){
		int v=e[i].to;  
		if(v==fa) continue; 
		if(v==son[x]) dfs2(v,x,tp);  
		else dfs2(v,x,v); 
	} 
}		
int query(int x,int k){
	if(dep[x]-1<k) return 0;  
	if(k==0)  return x;   
	x=f[x][hb[k]];  
	k^=1<<hb[k]; 
	if(dep[x]-dep[top[x]]>=k) 
		return D[top[x]][dep[x]-dep[top[x]]-k];  
	else 
		return U[top[x]][k-dep[x]+dep[top[x]]];  
}
int main(){
	scanf("%d",&n); 
	for(int i=1;i<n;i++){
		int x,y;  
		scanf("%d%d",&x,&y);  
		add(x,y);  
		add(y,x); 
	}
	dfs(1,0);  
	dfs2(1,1,1);  
	for(int i=1;i<=n;i++)
		if(top[i]==i){
			int x=i,k=0;   
			while (x && k<len[i])
				U[i].push_back(x),k++,x=f[x][0];
			x=i,k=0;  
			while (x && k<len[i]) 
				D[i].push_back(x),k++,x=son[x];  
		} 
	for(int i=1;i<=19;i++)  
		for(int j=(1<<i-1);j<(1<<i);j++)
			hb[j]=i-1;    
	int ans=0;  
	scanf("%d",&m);  
	while (m--){
		int x,y;  
		scanf("%d%d",&x,&y);  
		x^=ans; y^=ans;  
		printf("%d\n",ans=query(x,y));  
	}			
	return 0; 
}
posted @ 2020-05-20 15:19  zjxxcn  阅读(125)  评论(0编辑  收藏  举报