Analysis
长链剖分(可能是重链剖分他兄弟吧)
我们预处理出每个点向上2的幂次祖先fa[k][u],每一条重链的链顶向上、向下重链长度个点。(储存在vector中,由于重链长度和不超过n,所以空间、时间都是O(n)的)
对于询问求u的k次祖先,我们可以拆成r+(k−r)次祖先,其中r是k的最高二进制位,r次祖先u·可以用fa[k][u]得到。由于性质1。所以我们可以在top[u`]处的vector中查询。
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<vector>
#define re register
#define in read()
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<1)+(res<<3)+(ch^48);
ch=getchar();
}
return f==1?res:-res;
}
const int N=3e5+10;
int n,m;
int nxt[N<<1],to[N<<1],head[N],ecnt=0;
inline void add(int x,int y){
nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;
}
int dep[N],fa[N][25],md[N],son[N];
int len[N],top[N];
void dfs1(int u,int fu){
md[u]=dep[u]=dep[fu]+1;fa[u][0]=fu;
for(re int i=1;i<20;++i)
if(fa[u][i-1]) fa[u][i]=fa[fa[u][i-1]][i-1];
else break;
for(re int e=head[u];e;e=nxt[e]){
int v=to[e];
if(v==fu) continue;
dfs1(v,u);
if(md[son[u]]<md[v]) son[u]=v,md[u]=md[v];
}
}
void dfs2(int u){
len[u]=md[u]-dep[top[u]]+1;
if(son[u]){
top[son[u]]=top[u];
dfs2(son[u]);
}
for(re int e=head[u];e;e=nxt[e]){
int v=to[e];
if(v==fa[u][0]||v==son[u]) continue;
top[v]=v;
dfs2(v);
}
}
vector<int> U[N],D[N];
int bit[N];//每个值的二进制位上最高位1的位置
inline int query(int x,int k){
if(k>dep[x]) return 0;if(!k) return x;
int d1=bit[k];k^=(1<<bit[k]);
int u=fa[x][d1];
if(!k) return u;
if(dep[u]-dep[top[u]]==k) return top[u];
if(dep[u]-dep[top[u]]>k) return D[top[u]][dep[u]-dep[top[u]]-k-1];
return U[top[u]][k-(dep[u]-dep[top[u]])-1];
}
int main(){
n=in;
for(re int i=1;i<n;++i){
int x=in,y=in;
add(x,y);add(y,x);
}
dfs1(1,0);
top[1]=1;dfs2(1);
for(re int i=1;i<=n;++i)
if(i==top[i]){//处理每条重链的链端,向上、向下链长长度的节点有哪些
int l=0,x=i;
while(l<len[i]&&x) x=fa[x][0],l++,U[i].push_back(x);///
l=0,x=i;
while(l<len[i]) x=son[x],l++,D[i].push_back(x);///
}
int cnt=1;
for(re int i=1;i<=n;++i){
if((i>>cnt)&1) cnt++;
bit[i]=cnt-1;
}
int ans=0;
m=in;
for(re int i=1;i<=m;++i){
int a=in,b=in;
a^=ans;b^=ans;
ans=query(a,b);
printf("%d\n",ans);
}
return 0;
}