• Gym100512D Dynamic LCA


    题目来源:2012-2013 Summer Petrozavodsk Camp, Andrew Stankevich Contest 42

    记当前根为 root,查询的两个节点为 u 和 v,子树、LCA 指以 1 为根的子树、LCA

    • u 和 v 都不在 root 所在子树
      答案为 LCA(u, v)
    • u 和 v 都在 root 所在子树
      • 若 u 和 v 都在以 root 为根的子树中,答案为 LCA(u, v);
      • 若 u 和 v 其一以 root 为根的子树中,则u 到 v 的路径跨过 root,答案为 root;
      • 若 u 和 v 都不在以 root 为根的子树中,若 LCA(u, root) = LCA(v, root),则答案为 LCA(u, v);否则为 LCA(u, root) 和 LCA(v, root) 中深度较大者。
    • u 和 v 其一在 root 所在子树
      不妨设 v 在 root 所在子树。若 u 到 v 的路径跨过 root,即 v 在以 root 为根的子树中,则答案为 root;否则答案为 LCA(root, v)。
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <vector>
    
    const int MAXN = 100010;
    int n, m, root, dep[MAXN], f[MAXN][20], subtr[MAXN];
    char opt[10];
    std::vector<int> son[MAXN];
    
    void dfs(int u, int fa) {
        if (fa == 1) subtr[u] = u;
        else subtr[u] = subtr[fa];
        dep[u] = dep[fa] + 1;
        f[u][0] = fa;
        for (int i = 0; i < 19; ++i) {
            f[u][i + 1] = f[f[u][i]][i];
        }
        for (auto v : son[u]) {
            if (v == fa) continue;
            dfs(v, u);
        }
    }
    
    int LCA(int x, int y) {
        if (dep[x] < dep[y]) std::swap(x, y);
        for (int i = 19; i >= 0; --i) {
            if (dep[f[x][i]] >= dep[y]) x = f[x][i];
            if (x == y) return x;
        }
        for (int i = 19; i >= 0; --i) {
            if (f[x][i] != f[y][i]) {
                x = f[x][i];
                y = f[y][i];
            }
        }
        x = f[x][0];
        return x;
    }
    
    int main() {
        freopen("dynamic.in", "r", stdin);
        freopen("dynamic.out", "w", stdout);
        while (~scanf("%d", &n) && n) {
            root = 1;
            for (int i = 1; i <= n; ++i) {
                son[i].clear();
                memset(f[i], 0, sizeof(f[i]));
            }
            int u, v;
            for (int i = 1; i < n; ++i) {
                scanf("%d%d", &u, &v);
                son[u].push_back(v);
                son[v].push_back(u);
            }
            dfs(1, 0);
            scanf("%d", &m);
            while (m--) {
                scanf("%s", opt);
                if (opt[0] == '?') {
                    scanf("%d%d", &u, &v);
                    if (root == 1) {
                        printf("%d\n", LCA(u, v));
                        continue;
                    }
                    int x = subtr[u], y = subtr[v], t = subtr[root];
                    if (x != t && y != t) {
                        printf("%d\n", LCA(u, v));
                    } else if (x == t && y == t) {
                        int a = LCA(u, root), b = LCA(v, root);
                        if (a == root && b == root) printf("%d\n", LCA(u, v));
                        else if (a != root && b != root) {
                            if (a == b) printf("%d\n", LCA(u, v));
                            else printf("%d\n", dep[a] > dep[b] ? a : b);
                        }
                        else printf("%d\n", root);
                    } else {
                        if (x == t) {
                            std::swap(x, y);
                            std::swap(u, v);
                        }
                        int temp = LCA(v, root);
                        if (temp == root) printf("%d\n", root);
                        else printf("%d\n", temp);
                    }
                } else {
                    scanf("%d", &u);
                    root = u;
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Poi之Word文档结构介绍
    Cannot create PoolableConnectionFactory (ORA-28040: No matching authentication protocol
    ZipFile和ZipInputSteam解压zip文件
    Java读取其他jar包里的配置文件
    安装oracle后不能连接问题
    JDBC oracle 错误总结
    vimplugin破解
    SQL之left join、right join、inner join
    ELK之安装searchguard后默认管理员用户admin修改
    CentOS使用systemctl daemon-reload报错Error getting authority: Error initializing authority: Error calling StartServiceByName for org.freedesktop.PolicyKit1: Timeout was reached (g-io-error-quark, 24)解决办法
  • 原文地址:https://www.cnblogs.com/TouhouSumi/p/16582159.html
Copyright © 2020-2023  润新知