题解:换根操作是老套路,这个有一问是求儿子中的信息,要用bfs序来维护;
要注意的是要求儿子的bfs序和本身并不是连续的。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define MAXN 100010
#define MAXM 200010
#define MAXL 20
#define INF (MAXN-2)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
struct edges{
int to,pre;
}e[MAXM];
int etop,h[MAXN],dep[MAXN],son[MAXN],L[MAXN];
int in[MAXN],out[MAXN],bin[MAXN],R[MAXN];
inline int add_edge(int u,int v)
{
etop++;
e[etop].to=v;
e[etop].pre=h[u];
h[u]=etop;
return 0;
}
int fa[MAXN],up[MAXN][MAXL],times[MAXN],btimes[MAXN];
int bfs_clock,dfs_clock;
inline int dfs(int x,int f)
{
times[in[x]=++dfs_clock]=x;
up[x][0]=fa[x]=f;dep[x]=dep[f]+1;
for(int i=1;i<MAXL;i++)
up[x][i]=up[up[x][i-1]][i-1];
for(int i=h[x];i;i=e[i].pre)
if(e[i].to^fa[x]) dfs(e[i].to,x);
out[x]=dfs_clock;return 0;
}
queue<int> q;
inline int bfs(int s)
{
while(!q.empty()) q.pop();
bin[s]=++bfs_clock;
q.push(s);btimes[bfs_clock]=s;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=h[x];i;i=e[i].pre)
if(e[i].to^fa[x])
{
bin[e[i].to]=++bfs_clock;
L[x]=min(L[x],bfs_clock);
R[x]=max(R[x],bfs_clock);
son[x]++;btimes[bfs_clock]=e[i].to;q.push(e[i].to);
}
}
return 0;
}
inline int getlx(int x,int y)
{
for(int i=MAXL-1;i>=0;i--)
if(dep[up[x][i]]>dep[y])
x=up[x][i];
return x;
}
struct segment{
int l,r,minn,rm;
segment *ch[2];
}*brt,*rt,pool[MAXN<<2];int pool_top;
inline int push_up(segment* &rt)
{
rt->minn=min(rt->ch[0]->minn,rt->ch[1]->minn);
rt->rm=min(rt->ch[0]->rm,rt->ch[1]->rm);
return 0;
}
inline int build(segment* &rt,int l,int r,int k)
{
rt=&pool[++pool_top];
rt->l=l;rt->r=r;
rt->ch[0]=rt->ch[1]=NULL;
if(l==r) return rt->minn=rt->rm=(k?times[l]:btimes[r]);
int mid=(l+r)>>1;
build(rt->ch[0],l,mid,k);
build(rt->ch[1],mid+1,r,k);
push_up(rt);return 0;
}
inline int update(segment* &rt,int s,int t,int v)
{
int l=rt->l,r=rt->r;
if(s<=l&&r<=t) return (v^INF)?(rt->minn=rt->rm):(rt->minn=v);
int mid=(l+r)>>1;
if(s<=mid) update(rt->ch[0],s,t,v);
if(mid<t) update(rt->ch[1],s,t,v);
push_up(rt);return 0;
}
inline int query(segment* &rt,int s,int t)
{
if(s>t) return INF;
int l=rt->l,r=rt->r;
if(s<=l&&r<=t) return rt->minn;
int mid=(l+r)>>1,ans=INF;
if(s<=mid) ans=min(ans,query(rt->ch[0],s,t));
if(mid<t) ans=min(ans,query(rt->ch[1],s,t));
push_up(rt);return ans;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n,q;scanf("%d%d",&n,&q);
memset(h,0,sizeof(h)),etop=0;
for(int i=1;i<n;i++)
{
int u,v;scanf("%d%d",&u,&v);
add_edge(u,v),add_edge(v,u);
}
int root=1;
dfs_clock=0;dfs(root,INF);
memset(son,0,sizeof(son));
for(int i=1;i<=n;i++) L[i]=INF,R[i]=0;
bfs_clock=0;bfs(root);
pool_top=0;build(brt,1,n,0);build(rt,1,n,1);
// for(int i=1;i<=n;i++) debug(i)sp,debug(in[i])sp,debug(out[i])ln;
// cout ln;
// for(int i=1;i<=n;i++) debug(i)sp,debug(bin[i])sp,debug(L[i])sp,debug(R[i])ln;
while(q--)
{
int x,y,c;scanf("%d%d",&x,&y);
if(x==y)
{
if(fa[y]==INF&&!son[y])
{
printf("no answers!\n");
continue;
}
int ans1=min(fa[y],query(brt,L[y],R[y])),
ans2=(y^1)?1:2;
printf("%d %d\n",ans1,ans2);
}
else if(in[y]<=in[x]&&in[x]<=out[y])
{
int lx=getlx(x,y);
if(fa[y]==INF&&son[y]==1)
{
printf("no answers!\n");
continue;
}
int ans1=min(fa[y],min(query(brt,L[y],bin[lx]-1),query(brt,bin[lx]+1,R[y])));
update(rt,in[lx],out[lx],INF);update(rt,y,y,INF);int ans2=query(rt,1,n);
printf("%d %d\n",ans1,ans2);
update(rt,in[lx],out[lx],0);update(rt,y,y,0);
}
else{
// cout<<"here"<<endl;
if(!son[y])
{
printf("no answers!\n");
continue;
}
int ans1=query(brt,L[y],R[y]),ans2=query(rt,in[y]+1,out[y]);
printf("%d %d\n",ans1,ans2);
}
}
printf("\n");
}
return 0;
}