[CF770C] BSUでオンラインコース - LCA

あります\(N- \)は、木、の合計のノード\(Q \)回のクエリ、すべての与えられたクエリ\(3 \)ポイント、開始点と終了点を見つけて、不完全なこの3点に重畳された二人はパス内のノードの最も一般的な数。

解決

列挙共通点、答えは\((DIS(B )+ DIS(C) - DIS(B、C))/ 2 + 1 \)

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;

int n,q,t1,t2,t3;
vector <int> g[N];
int dep[N],fa[N][20],vis[N];

void dfs(int p) {
    vis[p]=1;
    for(int q:g[p]) {
        if(vis[q]) continue;
        dep[q]=dep[p]+1;
        fa[q][0]=p;
        dfs(q);
    }
}

int lca(int p,int q) {
    if(dep[p]<dep[q]) swap(p,q);
    for(int i=18;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
    for(int i=18;i>=0;--i) if(fa[p][i]-fa[q][i]) p=fa[p][i], q=fa[q][i];
    if(p-q) return fa[p][0];
    return p;
}

int dist(int p,int q) {
    int l=lca(p,q);
    return dep[p]+dep[q]-2*dep[l];
}

int calc(int a,int b,int c) {
    return (dist(a,b)+dist(a,c)-dist(b,c))/2;
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>q;
    for(int i=1;i<n;i++) {
        cin>>t1;
        g[i+1].push_back(t1);
        g[t1].push_back(i+1);
    }
    dep[1]=1;
    dfs(1);
    for(int i=1;i<=18;i++) {
        for(int j=1;j<=n;j++) {
            fa[j][i]=fa[fa[j][i-1]][i-1];
        }
    }
    for(int i=1;i<=q;i++) {
        cin>>t1>>t2>>t3;
        cout<<max(max(calc(t1,t2,t3),calc(t2,t3,t1)),calc(t3,t1,t2))+1<<endl;
    }
}

おすすめ

転載: www.cnblogs.com/mollnn/p/12588947.html