题意:

给定前序遍历和中序遍历,问u和v的lca
(先是中序,后是中序)

题解:

方法一:

参考题解
将树映射到一颗BST上,在BST上找到答案然后再映射回原本的树
方法二:
参考题解
已知某个树的根结点,若a和b在根结点的左边,则a和b的最近公共祖先在当前子树根结点的左子树寻找,如果a和b在当前子树根结点的两边,在当前子树的根结点就是a和b的最近公共祖先,如果a和b在当前子树根结点的右边,则a和b的最近公共祖先就在当前子树的右子树寻找。中序加先序可以唯一确定一棵树,在不构建树的情况下,在每一层的递归中,可以得到树的根结点,在此时并入lca算法可以确定两个结点的公共祖先~

代码:

#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <cstdio>
#include <map>

using namespace std;

int m, n;
int opre[10009], oin[10009];
int pre[10009], in[10009];
map<int, int> otos, stoo;

int main()
{
    cin >> m >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> oin[i];
        otos[oin[i]] = i;
        stoo[i] = oin[i];
    }
    for (int i = 0; i < n; i++)
    {
        cin >> opre[i];
        pre[i] = otos[opre[i]];
    }

    for (int i = 0; i < m; i++)
    {
        int u, v;
        int a;
        bool flag1 = true, flag2 = true;
        cin >> u >> v;
        if (otos.find(u) == otos.end())
            flag1 = false;
        if (otos.find(v) == otos.end())
            flag2 = false;
        if (!flag1 || !flag2)
        {
            if (!flag1 && !flag2)
                printf("ERROR: %d and %d are not found.\n", u, v);
            else
                printf("ERROR: %d is not found.\n", flag1 == false ? u : v);
            continue;
        }
        u = otos[u];
        v = otos[v];
        for (int j = 0; j < n; j++)
        {
            a = pre[j];
            if (a > u && a < v || a < u && a > v || a == u || a == v)
                break;
        }
        u = stoo[u];
        v = stoo[v];
        a = stoo[a];
        if (a == u || a == v)
            printf("%d is an ancestor of %d.\n", a, a == u ? v : u);
        else
            printf("LCA of %d and %d is %d.\n", u, v, a);
    }
    return 0;
}
#include <iostream>
#include <vector>
#include <map>
using namespace std;
map<int, int> pos;
vector<int> in, pre;
void lca(int inl, int inr, int preRoot, int a, int b) {
    if (inl > inr) return;
    int inRoot = pos[pre[preRoot]], aIn = pos[a], bIn = pos[b];
    if (aIn < inRoot && bIn < inRoot)
        lca(inl, inRoot-1, preRoot+1, a, b);
    else if ((aIn < inRoot && bIn > inRoot) || (aIn > inRoot && bIn < inRoot))
        printf("LCA of %d and %d is %d.\n", a, b, in[inRoot]);
    else if (aIn > inRoot && bIn > inRoot)
        lca(inRoot+1, inr, preRoot+1+(inRoot-inl), a, b);
    else if (aIn == inRoot)
            printf("%d is an ancestor of %d.\n", a, b);
    else if (bIn == inRoot)
            printf("%d is an ancestor of %d.\n", b, a);
}
int main() {
    int m, n, a, b;
    scanf("%d %d", &m, &n);
    in.resize(n + 1), pre.resize(n + 1);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &in[i]);
        pos[in[i]] = i;
    }
    for (int i = 1; i <= n; i++) scanf("%d", &pre[i]);
    for (int i = 0; i < m; i++) {
        scanf("%d %d", &a, &b);
        if (pos[a] == 0 && pos[b] == 0)
            printf("ERROR: %d and %d are not found.\n", a, b);
        else if (pos[a] == 0 || pos[b] == 0)
            printf("ERROR: %d is not found.\n", pos[a] == 0 ? a : b);
        else
            lca(1, n, 1, a, b);
    }
    return 0;
}