RMQ求LCA

題目鏈接:https://www.luogu.org/problem/P3379 

學習鏈接:https://blog.csdn.net/Diogenes_/article/details/81412316

 預處理時間複雜度O(NlogN)

 查詢時間複雜度O(1)

#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define pb push_back
using namespace std;
const int N = 5e5+1;        //點數
int st[N],cnt,euler[N*2],deep[N];
vector<int> nxt[N];
void dfs(int u,int f) {
    deep[u] = deep[f]+1;
    euler[++cnt] = u;
    st[u] = cnt;
    for(auto v:nxt[u]) {
        if(v==f) continue;
        dfs(v,u);
        euler[++cnt] = u;
    }
}
//------------------------------------------------------
int dp[2*N][25];
int cal(int x,int y) {
    if(deep[x]<deep[y]) return x;
    else return y;
}
void RMQ(int n){
    for(int i = 1; i <= n; i++) dp[i][0] = euler[i];
    for(int i = 1; i < 25; i++)
        for(int j = 1; j + (1 << i) - 1 <= n; j++)
            dp[j][i] = cal(dp[j][i-1],dp[(j+(1<<(i-1)))][i-1]);
}
int q_min(int x,int y){
    int k = (int)((log(y - x + 1) * 1.0) / log(2.0));
    return cal(dp[x][k],dp[y - (1<<k) + 1][k]);
}
//-------------------------------------------------------
int q_lca(int u,int v) {
    if(st[u]>st[v]) swap(u,v);
    return q_min(st[u],st[v]);
}
//-------------------------------------------------------
int n,m,root;
int main() {
    scanf("%d%d%d",&n,&m,&root);
    int u,v;
    rep(i, 1, n-1) {
        scanf("%d%d",&u,&v);
        nxt[u].pb(v);
        nxt[v].pb(u);
    }
    dfs(root,0);
    RMQ(2*n);

    rep(i, 1, m) {
        scanf("%d%d",&u,&v);
        printf("%d\n",q_lca(u,v));
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章