长链剖分练习

练习1 给定树, 强制在线询问k级祖先

https://zhuanlan.zhihu.com/p/25984772

知乎介绍的挺详细的, 放个我打的板子

int n, m;
int sz[N], mx[N], dep[N], Log[N];
int fa[N][20], son[N], top[N];
vector<int> g[N], up[N], down[N];

void dfs(int x, int f, int d) {
	sz[x]=1,mx[x]=dep[x]=d,fa[x][0]=f,son[x]=x;
	for (int i=1; (1<<i)<dep[x]; ++i) {
		fa[x][i] = fa[fa[x][i-1]][i-1];
	}
	for (int y:g[x]) if (y!=f) {
		dfs(y,x,d+1);sz[x]+=sz[y];
		if (mx[y]>mx[x]) son[x]=y,mx[x]=mx[y];
	}
}

void dfs2(int x, int tf) {
	top[x]=tf;
	if (son[x]!=x) dfs2(son[x],tf);
	for (int y:g[x]) if (y!=fa[x][0]&&y!=son[x]) dfs2(y,y);
}

void init() {
	dfs(1,0,1),dfs2(1,1);
	Log[0] = -1;
	REP(i,1,n) Log[i]=Log[i>>1]+1;
	REP(i,1,n) if (top[i]==i) {
		int x = i;
		REP(j,0,mx[i]-dep[i]) up[i].pb(x),x=fa[x][0];
		x = i;
		REP(j,0,mx[i]-dep[i]) down[i].pb(x),x=son[x];
	}
}

int query(int x, int k) {
	if (!k) return x;
	if (k>=dep[x]) return 0;
	x = fa[x][Log[k]], k ^= 1<<Log[k];
	if (dep[x]-dep[top[x]]>=k) return down[top[x]][dep[x]-dep[top[x]]-k];
	return up[top[x]][k-dep[x]+dep[top[x]]];
}

int main() {
	scanf("%d", &n);
	REP(i,2,n) {
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].pb(v),g[v].pb(u);
	}
	init();
	int ans = 0;
	scanf("%d", &m);
	REP(i,1,m) {
		int x, k;
		scanf("%d%d", &x, &k);
		x ^= ans, k ^= ans;
		printf("%d\n", ans=query(x,k));
	}
}

猜你喜欢

转载自www.cnblogs.com/uid001/p/10493831.html