凭借记忆勉强写出的倍增LCA。
http://www.lydsy.com/JudgeOnline/problem.php?id=4281
/************************************************************** Problem: 4281 User: 1349367067 Language: C++ Result: Accepted Time:6316 ms Memory:130180 kb ****************************************************************/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> usingnamespacestd; intn,m,k; intfa[1000011]={}; intLCA[1000011][31]={},D; intdepth[1000011]={}; intpre[31]={}; voidmake_LCA() { D=0; intT=1; while(T<n) T*=2,D++; pre[0]=1; for(inti=1;i<=D;i++) pre[i]=pre[i-1]*2; for(inti=1;i<=n;i++) LCA[i][0]=fa[i]; for(inti=1;i<=D;i++) for(intj=1;j<=n;j++) { if(LCA[j][i-1]==-1) LCA[j][i]=-1; else LCA[j][i]=LCA[LCA[j][i-1]][i-1]; } } voidfind_depth(intx) { if(depth[x]!=0) return; if(depth[fa[x]]==0) find_depth(fa[x]); depth[x]=depth[fa[x]]+1; return; } intfind_LCA(intx,inty) { if(depth[x]<depth[y]) swap(x,y); for(inti=D;i>=0;i--) if(depth[LCA[x][i]]>=depth[y]) x=LCA[x][i]; if(x==y) returnx; for(inti=D;i>=0;i--) if(LCA[x][i]!=LCA[y][i]) { x=LCA[x][i];y=LCA[y][i]; } returnfa[x]; } voidinit() { scanf("%d%d%d",&n,&m,&k); intl,r; fa[1]=-1;depth[1]=1; for(inti=1;i<n;i++) { scanf("%d%d",&l,&r); if(l>r) swap(l,r); fa[r]=l; } make_LCA(); for(inti=1;i<=n;i++) find_depth(i); } intup_LCA(intx,intt) { for(inti=D;i>=0;i--) if(t>=pre[i]) { x=LCA[x][i];t-=pre[i]; } returnx; } voidwork() { intd,t,lca,len; for(inti=1;i<=k;i++) { scanf("%d%d",&d,&t); lca=find_LCA(m,d); len=depth[lca]*2-depth[m]-depth[d]; len=-len; if(len<=t) { m=d; printf("%d ",m); } else { if((depth[m]-depth[lca])==t) m=lca; else if((depth[m]-depth[lca])>t) m=up_LCA(m,t); else m=up_LCA(d,len-t); printf("%d ",m); } } } intmain() { init(); work(); return0; }