【Vijos】lxhgww的奇思妙想(长链剖分)

题面

给定一棵树,每次询问一个点的\(k\)次祖先,强制在线。
Vijos

题解

长链剖分
链接暂时咕咕咕了。
现在可以戳链接看题解了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 300300
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int hson[MAX],dep[MAX],md[MAX],len[MAX];
int p[MAX][20],top[MAX],n,hbit[MAX];
void dfs1(int u,int ff)
{
	md[u]=dep[u]=dep[ff]+1;p[u][0]=ff;
	for(int i=1;i<20;++i)
		if(p[u][i-1])p[u][i]=p[p[u][i-1]][i-1];
		else break;
	for(int i=h[u];i;i=e[i].next)
	{
		int v=e[i].v;if(v==ff)continue;
		dfs1(v,u);
		if(md[v]>md[hson[u]])hson[u]=v,md[u]=md[v];
	}
}
void dfs2(int u,int tp)
{
	top[u]=tp;len[u]=md[u]-dep[top[u]]+1;
	if(hson[u])dfs2(hson[u],tp);
	for(int i=h[u];i;i=e[i].next)
		if(e[i].v!=p[u][0]&&e[i].v!=hson[u])
			dfs2(e[i].v,e[i].v);
}
vector<int> U[MAX],D[MAX];
int Query(int u,int k)
{
	if(k>dep[u])return 0;if(!k)return u;
	u=p[u][hbit[k]];k^=1<<hbit[k];
	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=read();
	for(int i=1;i<n;++i)
	{
		int u=read(),v=read();
		Add(u,v);Add(v,u);
	}
	dfs1(1,0);dfs2(1,1);
	for(int i=1;i<=n;++i)
		if(i==top[i])
		{
			int l=0,x=i;
			while(l<len[i]&&x)x=p[x][0],++l,U[i].push_back(x);
			l=0,x=i;
			while(l<len[i])x=hson[x],++l,D[i].push_back(x);
		}
	int mx=1;
	for(int i=1;i<=n;++i)
	{
		if((i>>mx)&1)++mx;
		hbit[i]=mx-1;
	}
	int m=read(),ans=0;
	while(m--)
	{
		int u=read()^ans,v=read()^ans;
		printf("%d\n",ans=Query(u,v));
	}
	return 0;
}

posted @ 2018-08-10 21:05  小蒟蒻yyb  阅读(1733)  评论(3编辑  收藏  举报