A and B and Lecture Rooms

A and B and Lecture Rooms

https://ac.nowcoder.com/acm/problem/110856

这题的思维难度并不很大

但是细节有一点点需要注意

首先两点间的距离如果是奇数必定无解

如果是偶数,那么可以找到中间的那个点,必定满足条件

而且从延伸出去的各种分支,只要不是包含的分枝都是满足条件的

因为两点都是从拐过去的

这个规律在任意时刻都是适用的

但是当deep[l]==deep[r]注意一下计算方式

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5+10; 
int n;
struct edge{
    int to,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v){
    d[++cnt] = (edge){v,head[u]},head[u] = cnt;
}
int fa[maxn][20],deep[maxn],siz[maxn];
void dfs(int u,int faa)
{
    fa[u][0] = faa, deep[u] = deep[faa]+1; siz[u] = 1;
    for(int i=1;i<=18;i++)
        fa[u][i] = fa[fa[u][i-1]][i-1];
    for(int i=head[u];i;i=d[i].nxt )
    {
        int v = d[i].to;
        if( v==faa )    continue;
        dfs(v,u);
        siz[u] += siz[v];
    }
}
int X,Y;
int lca(int x,int y)
{
    if( deep[x]<deep[y] )    swap(x,y);
    for(int i=18;i>=0;i--)
        if( deep[fa[x][i]]>=deep[y] )    x = fa[x][i];
    if( x==y )    return x;
    for(int i=18;i>=0;i--)
        if( fa[x][i]!=fa[y][i] )
            x=fa[x][i], y = fa[y][i];
    X=x,Y=y;
    return fa[x][0];
}
int k_th(int x,int depth)
{
    for(int i=18;i>=0;i--)
        if( depth&(1<<i) )    x=fa[x][i];
    return x;
}
int dis(int l,int r,int ff){
    return deep[l]+deep[r]-2*deep[ff];
}
int main()
{
    cin >> n;
    for(int i=1;i<n;i++)
    {
        int l,r; scanf("%d%d",&l,&r);
        add(l,r); add(r,l);
    }
    deep[0]=-1; dfs(1,0);
    int q; cin >> q;
    while( q-- )
    {
        int l,r; scanf("%d%d",&l,&r);
        int ff = lca(l,r);
        int juli = dis(l,r,ff);
        if( l==r )    cout << n << endl;
        else if( juli%2==1 )    cout << 0 << endl;
        else
        {
            if( deep[l]==deep[r] )
            {
                int nxtl=nxt_th(l,juli/2),nxtr=nxt_th(r,juli/2);
                cout << n-siz[nxtl]-siz[nxtr] << endl;
                continue;
            }
            int mid,nxt,kl;
            if( deep[l]>deep[r] )
                mid = k_th(l,juli/2),nxt=k_th(l,juli/2-1);
            else
                mid = k_th(r,juli/2),nxt=k_th(r,juli/2-1);
            cout << siz[mid]-siz[nxt] << endl;
        }
    }
}
全部评论

相关推荐

Java抽象带篮子:难蚌,点进图片上面就是我的大头😆
点赞 评论 收藏
分享
尊嘟假嘟点击就送:加v细说,问题很大
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-27 10:48
点赞 评论 收藏
分享
评论
2
收藏
分享
牛客网
牛客企业服务