AcWing 3555. 二叉树

发布时间 2023-03-26 20:24:03作者: 高尔赛凡尔娟

https://www.acwing.com/problem/content/description/3558/

输入样例:
1
8 4
2 3
4 5
6 -1
-1 -1
-1 7
-1 -1
8 -1
-1 -1
1 6
4 6
4 5
8 1
输出样例:
2
4
2
4

详解见代码内部

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18,MINN=-MAXN,INF=0x3f3f3f3f;
const LL N=2e6+10,M=2023;
const LL mod=998244353;
const double PI=3.1415926535;
#define endl '\n'
int n,m;
int father[N],L[N],R[N];
int find(int x,int a[])//从x这个点开始往上搜索父节点,并且存储在相应的数组中
{
    int res=0;//下标从0开始
    while(x!=1)//没有到达根节点
    {
        a[res++]=x;//离得更近的父节点装进去(注意自己也装进去了)
        x=father[x];//找父节点的父节点,依次往上递增寻找
    }
    a[res++]=1;//最后把根节点装进去
    return res;//返回这一条路的父节点们
}
int main()
{
    cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
    int T=1;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            LL x,y;
            cin>>x>>y;
            //有子节点,则记录
            if(x!=-1) father[x]=i;
            if(y!=-1) father[y]=i;
        }
        while(m--)
        {
            LL l,r;
            cin>>l>>r;
            //sum表示父节点的个数
            LL suml=find(l,L);//L储存所有l父节点的信息
            LL sumr=find(r,R);//R储存所有r父节点的信息
            //下标是从0开始的,所以倒过来-1
            //这里是从头开始往更深的地方寻找
            for(int i=suml-1,j=sumr-1;i>=0&&j>=0;i--,j--)
            {
                if(L[i]==R[j])//这里还一样的话,说明还可以在向下探索一下
                {
                    //此处有标记
                    suml--;
                    sumr--;
                }
                else break;//这里已经不一样了,直接退出
            }
            cout<<suml+sumr<<endl;
        }
    }
    return 0;
}