最近公共祖先

Iter-moon發表於2024-06-18

ST

#include<bits/stdc++.h>
    
using namespace std;
const int N = 1e5 + 5;
int dp[N][32];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int n, m; cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> dp[i][0];
    for (int j = 1; j <= 20; j++) {
        for (int i = 1; i + (1 << j) - 1 <= n; i++) {
            dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
        }
    }
    while (m--) {
        int l, r; cin >> l >> r;
        int k = log2(r - l + 1);
        cout << max(dp[l][k], dp[r - (1 << k) + 1][k]) << '\n';
    }
    return 0;
}

  

LCA

// (n + m) log(m)
#include<bits/stdc++.h>
    
using namespace std;
const int N = 5e5 + 5;
int n, m, s; //樹的結點個數、詢問的個數和樹根結點的序號
int dep[N], f[N][20];
vector <int> adj[N];

void dfs(int from, int fa) { // from 是兒子 fa 是父親
    dep[from] = dep[fa] + 1;
    f[from][0] = fa; //它的上一層是它的父親
    for (int i = 1; i <= 19; i++) {
        f[from][i] = f[f[from][i - 1]][i - 1];
    }
    for (int to : adj[from]) {
        if (to != fa) dfs(to, from);
    }
}

int lca(int from, int to) { // from 和 to 跳到同一層
    if (dep[from] < dep[to]) swap(from, to); // 只讓from 跳
    for (int i = 19; i >= 0; i--) {
        if (dep[f[from][i]] >= dep[to]) {
            from = f[from][i];
        }
    }
    if (from == to) return to; //恰好to是它的祖先
    for (int i = 19; i >= 0; i--) {
        if (f[from][i] != f[to][i]) { //如果不相同則讓它們走上去
            from = f[from][i]; to = f[to][i];
        }
    }
    return f[from][0];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> m >> s;
    for (int i = 1; i < n; i++) {
        int from, to; cin >> from >> to;
        adj[from].push_back(to);
        adj[to].push_back(from);
    }
    dfs(s, 0);
    while (m--) {
        int from, to; cin >> from >> to;
        cout << lca(from, to) << '\n';
    }
    return 0;
}

  

Trajan

// n + m
#include<bits/stdc++.h>
    
using namespace std;
const int N = 5e5 + 5;
int n, m, s, f[N], ans[N];
bool vis[N];
vector <int> adj[N];
vector <pair<int, int>> query[N];

int find(int x) {
    return f[x] == x ? x : f[x] = find(f[x]);
}

void Trajan(int from) {
    vis[from] = 1;
    for (int to : adj[from]) {
        if (!vis[to]) {
            Trajan(to);
            f[to] = from;
        }
    }
    for (auto [to, id] : query[from]) {
        if (vis[to]) ans[id] = find(to);
    } 
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> m >> s;
    for (int i = 1; i < n; i++) {
        int from, to; cin >> from >> to;
        adj[from].push_back(to);
        adj[to].push_back(from);
    }
    for (int i = 1; i <= m; i++) {
        int from, to; cin >> from >> to;
        query[from].push_back({to, i});
        query[to].push_back({from, i});
    }
    for (int i = 1; i < N; i++) f[i] = i;
    Trajan(s);
    for (int i = 1; i <= m; i++) cout << ans[i] << '\n';
    return 0;
}

  

相關文章