树上倍增裸题
%%%用树链剖分拿rank3的Evan大爷
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #define V G[p].v using namespace std; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } struct edge{ int u,v; int next; }; edge G[2000005]; int head[1000005],inum; inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; } int n,depth[1000005]; int fat[1000005][25]; inline void dfs(int u,int fa){ fat[u][0]=fa; depth[u]=depth[fa]+1; for (int p=head[u];p;p=G[p].next) if (V!=fa) dfs(V,u); } inline int Dis(int x,int y){ return depth[y]-depth[x]; } inline int LCA(int u,int v){ if (depth[u]<depth[v]) swap(u,v); for (int k=22;~k;k--) if ((depth[u]-depth[v])&(1<<k)) u=fat[u][k]; if (u==v) return v; for (int k=22;~k;k--) if (fat[u][k]!=fat[v][k]) u=fat[u][k],v=fat[v][k]; return fat[u][0]; } inline int Fat(int u,int d){ for (int k=22;~k;k--) if (d&(1<<k)) u=fat[u][k]; return u; } int main() { int iu,iv,K; int s,t,len; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(s); read(K); for (int i=1;i<n;i++) read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum); dfs(1,0); for (int k=1;k<=22;k++) for (int i=1;i<=n;i++) fat[i][k]=fat[fat[i][k-1]][k-1]; while (K--) { read(t); read(len); int lca=LCA(s,t); if (Dis(lca,s)+Dis(lca,t)<=len) s=t; else if (Dis(lca,s)>=len) s=Fat(s,len); else if (Dis(lca,s)+Dis(lca,t)>=len) s=Fat(t,Dis(lca,s)+Dis(lca,t)-len); printf("%d ",s); } return 0; }