Description
给一棵n个节点的树,m次询问一个节点x的k级祖先。强制在线
Solution
一个做法是倍增
另一个做法是长链剖分。同重链剖分一样,我们定义深度最大叶子所在儿子作为长儿子。
一个性质是,节点x的k级祖先所在重链长度不会小于k。正确性的话可以考虑反证一下。
也就是说,我们取出k的最高位二进制设为r。我们先让x向上跳r步,r所在的重链长度至少为r。对于每条重链我们维护它向上len个节点,沿着重链向下len个节点。那么剩下的k-r步我们可以一次跳完
于是这样做就是O(nlogn)预处理倍增,O(1)求一个节点的k级祖先
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
const int N=1000005;
struct edge {int y,next;} e[N*2];
int bl[N],mx[N],dep[N],fa[19][N];
int ls[N],high[N],edCnt;
int son[N],len[N];
std:: vector <int> U[N],D[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y) {
e[++edCnt]=(edge) {y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {x,ls[y]}; ls[y]=edCnt;
}
void dfs1(int x) {
int rec=0; mx[x]=dep[x];
rep(i,1,18) fa[i][x]=fa[i-1][fa[i-1][x]];
for (int i=ls[x];i;i=e[i].next) {
if (e[i].y==fa[0][x]) continue;
dep[e[i].y]=dep[x]+1,fa[0][e[i].y]=x;
dfs1(e[i].y);
if (mx[e[i].y]>mx[son[x]]) {
mx[x]=mx[e[i].y];
son[x]=e[i].y;
}
}
}
void dfs2(int x,int up) {
bl[x]=up; len[x]=mx[x]-dep[up]+1;
if (!son[x]) return ;
dfs2(son[x],up);
for (int i=ls[x];i;i=e[i].next) {
if (e[i].y!=fa[0][x]&&e[i].y!=son[x]) dfs2(e[i].y,e[i].y);
}
}
int get_up(int x,int k) {
if (k>dep[x]) return 0;
if (!k) return x;
x=fa[high[k]][x],k-=(1<<high[k]);
if (!k) return x;
int up=bl[x];
if (dep[x]-dep[up]==k) return up;
if (dep[x]-dep[up]<k) return U[up][k-dep[x]+dep[up]-1];
else return D[up][dep[x]-dep[up]-k-1];
}
int main(void) {
int n=read();
rep(i,1,n) {
high[i]=high[i-1];
if (i>>high[i]&1) continue;
high[i]++;
}
rep(i,2,n) add_edge(read(),read());
dfs1(1); dfs2(1,1);
rep(i,1,n) if (bl[i]==i) {
for (int x=i,d=1;d<=len[i]&&x;d++) x=fa[0][x],U[i].push_back(x);
for (int x=i,d=1;d<=len[i]&&x;d++) x=son[x],D[i].push_back(x);
}
for (int m=read(),lastans=0;m--;) {
int x=read(),y=read();
x^=lastans,y^=lastans;
lastans=get_up(x,y);
printf("%d\n", lastans);
}
return 0;
}